IBM VisualAge® for Java™,Version3.5 

C++ Access Builder Note! Before using this information and the product it supports, be sure to read the general information under Notices.

Edition notice This edition applies to Version 3.5 of IBM VisualAge for Java and to all subsequent releases and modifications until otherwise indicated in new editions. © Copyright International Business Machines Corporation 1997, 2000. All rights reserved. US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. Contents

Chapter 1. ++ Access Builder .....1 Chapter 7. Testing the client from C++ Access Builder: overview ...... 1 program main...... 41 Language Elements Used in Mapping Java to C++. . 3 Inheritance ...... 3 Chapter 8. Deploying the client as a Constructors and destructors ...... 5 stand-alone application ...... 43 Methods ...... 6 Membervariables...... 7 Operators...... 8 Chapter 9. Tutorial ...... 45 Global definitions ...... 11 Sample: accessing a C++ ...... 45 Pointers ...... 13 Objectives ...... 45 References ...... 14 Time required ...... 45 Unionsandenums...... 16 Beforeyoubegin...... 45 Conversion functions ...... 17 Description ...... 45 Type conversion ...... 18 Running the sample program ...... 46 Design Considerations with the C++ Access Builder 20 Add the project to the workbench ...... 46 Businesslogic...... 20 RunthesampleintheIDE...... 46 Wrapper classes ...... 22 Developthesampleprogram...... 47 Memoryallocation...... 24 Add the project to the workbench ...... 47 Classes generated by the C++ Access Builder . . . 26 Generate the C++ access beans and wrapper files 47 C++ Access Builder limitations ...... 29 Createthesharedlibrary...... 47 Create the client class ...... 48 Chapter 2. Using the C++ Access Add the StStack bean to the Visual Composition Builder...... 31 Editor...... 48 Create the client program GUI ...... 48 Accessing C++ services: overview ...... 31 Connect the client program GUI ...... 48 Run your sample program in the IDE ....49 Chapter 3. Preparing to Generate C++ Run the sample program from the command line. . 50 Access Beans ...... 33 Startthesample...... 50 Creating a package for C++ access beans ....33 Run the sample as an application from the Creating C++ header files for interfaces .....33 commandline...... 50

Chapter 4. Generating C++ access Appendix. Reference Information . . . 51 beans and wrapper files ...... 35 Makefile targets ...... 51

Chapter 5. Creating Shared Libraries 37 Notices ...... 53 Creatingasharedlibrary...... 37 Creating a shared library without a makefile . . . 38 Programming information . . 57

Chapter 6. Creating a client using C++ Trademarks and service marks ....59 access beans ...... 39

© Copyright IBM Corp. 1997, 2000 iii iv C++ Access Builder Chapter 1. C++ Access Builder

C++ Access Builder: overview Java™ software developers face a number of problems when enabling Java programs to access C++ services. Fortunately, these problems are largely resolved by the C++ Access Builder. This VisualAge® for Java tool makes it easy for a Java client program, run as a stand-alone application, to access C++ services locally.

The C++ Access Builder generates code in the form of access beans and associated C++ files that enable your Java program to access existing C++ classes. It is designed to integrate C++ objects as seamlessly as possible, so programmers get the impression that the objects are actually implemented in Java. The C++ Access Builder also generates a makefile. The makefile automatically builds a library that enables C++ classes to be accessed as native methods.

The source code generated by the C++ Access Builder works in conjunction with the Java Native Interface (JNI) Specification, Release 1.1. This specification is implemented in the 1.1 version of the JavaSoft Java Developers Kit (JDK). JNI is a native programming interface that allows Java code to interoperate with libraries written in other programming languages, such as C and C++. The C++ Access Builder generates a makefile for the compiler you define; if your compiler is not supported, you may have to modify the generated makefile to work with your compiler.

The C++ Access Builder consists of two components: a generation-time tool and a run-time class library.

Generation-time tool The generation-time tool uses a SmartGuide to start and control the code-generation activities of the C++ Access Builder. Typically, the C++ Access Builder generates access beans and C++ wrapper files. Information about using the C++ Access Builder is found in the topic “Generating C++ access beans and wrapper files”.

Run-time class library The run-time class library provides execution-time support to the access beans and associated files generated by the C++ Access Builder. The class library hides the complexity of the generated code and provides the generated code with some required generic services.

The C++ Access Builder generation tool generates to the run-time class library com.ibm.ivj.eab.j2cppaccess.

For additional information about the individual C++ Access Builder run-time classes and their methods, see the information on IBM® in the Reference online help.

How does the C++ Access Builder work? When accessing another object-oriented language from Java using the procedural native code interface defined by JNI, there are several problems that must be addressed: v No JNI support for the instantiation of C++ classes.

© Copyright IBM Corp. 1997, 2000 1 v No Java support for accessing methods and members of C++ objects. v No Java support for operator overloading. v No Java support for passing objects by value and reference. v No Java support for several C++ primitive types, including unsigned int and signed char. To help address these problems, the C++ Access Builder generates a Java class to represent each C++ class. It also generates a C++ wrapper that can be safely invoked using the C native method for the Java virtual machine. This C++ wrapper interfaces with the original C++ class.

When a Java representative class is instantiated, a corresponding C++ class is instantiated and a reference to the new C++ object is stored by the new Java object. The Java object uses this reference to invoke methods and access members of the corresponding C++ object. This bridging technique reproduces inheritance relationships between imported C++ classes on the Java side and also supports polymorphic C++ methods. Those C++ class methods which expect objects to be passed as parameters, or to return C++ objects, are accessible from Java using the Java representative objects as parameters instead.

In the case of static members, access is possible without first instantiating the object pair.

The implementation of the C++ classes to be interfaced can be provided by C++ files, shared libraries, or as a combination of both. This allows the user to extend an existing C++ library by user-defined subclasses before using the C++ Access Builder to generate the Java interface.

The C++ Access Builder also maps C++ code that does not belong to a particular C++ class definition, such as overloaded non-member operators, global functions, and global variables. This code is represented by a special Java Statics class that contains Java access methods for each C++ declaration that was not part of any C++ class.

2 C++ Access Builder C++ Access Builder class selection Because the C++ Access Builder resolves typedef clauses and #define compiler directives, it can parse the whole hierarchy of include files for a given class definition file. Without an appropriate selection scheme indicating which classes are to be wrapped, all found C++ classes are mapped, including those found in the standard include files.

To ensure that only the desired C++ classes are wrapped, the C++ Access Builder uses a mechanism comparable to the Java CLASSPATH. The C++ Access Builder maintains a list of directories, referred to here as J2CPP_CLASSPATH, to determine whether a found C++ class is to be mapped to Java or not. For C++ classes which are to be mapped to Java, the following predicate must hold:

C++ class contained in class definition file contained in directory element of J2CPP_CLASSPATH

In other words, a C++ class is mapped if it is contained in a class definition file that is located in one of the member directories of J2CPP_CLASSPATH. The C++ class may be a declaration of a class, a pointer to a class, or a reference to a class.

The default class path used by the C++ Access Builder is the set of all directory prefixes of the class definition files specified in the SmartGuide. This means that J2CPP_CLASSPATH only needs to be set explicitly if classes are to be mapped which are defined in files other than those specified in the SmartGuide, such as those included using #include.

J2CPP_CLASSPATH can be modified one of the following ways: v By specifing the directories in the Add directories that contain additional header files to wrap field on the first page of the SmartGuide. v By setting the J2CPP_CLASSPATH environment variable. A file named keyword.ignore is found in the help directory. It specifies any keywords that you want to ignore. If the C++ Access Builder parser cannot parse a particular word, then you can direct the parser to ignore the word by adding it to the keyword.ignore file.

Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Generating C++ access beans and wrapper files

Makefile targets

Language Elements Used in Mapping Java to C++

Inheritance Java does not allow multiple inheritance. The C++ Access Builder reproduces single-inheritance relationships between C++ classes on the Java side and their corresponding Java representative classes. If multiple inheritance is detected in the

Chapter 1. C++ Access Builder 3 C++ class definitions, the program will issue a warning and will consider the first parent class encountered to be the only parent class.

All generated Java representative classes are derived from a special root class called com.ibm.ivj.eab.j2cpp.__J2CPP_ . This class is predefined as part of the installation process of the C++ Access Builder. All generated Java representative classes inherit indirectly from their parent class according to the mapped C++ inheritance chains, or they inherit directly from the __J2CPP_ class.

For example, if a C++ class definition file contains two classes, A and B, where B inherits from A, two corresponding Java classes named A and B would be generated: class A extends __J2CPP_ { ... }

class B extends A { ... }

In this corresponding Java example, the C++ class Circle inherits from the class Shape: class Shape { public: Shape(); xShape();

virtual void Move (int xdelta, int ydelta); virtual void Draw() const; virtual int Area() const; virtual void Title (char* title);

private: int x_, y_; char title_[256]; }; class Circle : public Shape { public:

Circle(); Circle(int xorg, int yorg, int r); Circle(int r); Circle(const Circle& circ); xCircle();

void Move(int xdelta, int ydelta); void Draw() const; int Area() const;

private:

int x, y; int radius; };

The following example shows how you would access the C++ class Circle in Java: Shape myCircle = new Circle(5, 5, 8); myCircle.Title(“My Circle:”); myCircle.Draw(); int myArea = myCircle.Area(); or Circle myCircleb = new Circle(15); myArea = myCircleb.Area()

4 C++ Access Builder Constructors and destructors Methods Member variables Operators Global definitions Pointers References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Constructors and destructors Constructors The generated Java access beans and classes automatically instantiate their corresponding C++ classes when the Java constructor is called. This one-to-one relationship is preserved during the lifetime of the Java object.

If no constructor is found in the C++ class definition, a default constructor is generated automatically for the Java side.

See the “Inheritance” topic for an example of how to access C++ constructors.

Destructors Java contains a garbage collection mechanism that deletes objects which are no longer referenced. For this reason, there is no concept of a destructor that must be called explicitly. To execute additional cleanup code before the object is removed, Java provides the finalize routine. The finalize function is called before the Java garbage collector deletes the Java instance. The C++ Access Builder makes use of this concept by supplying a native finalize method, located in the corresponding C++ wrapper, for each generated Java class. This code invokes the C++ delete operator on the C++ object if the C++ object was allocated by a call made on the Java side. The finalize method is generated automatically, regardless of whether there was a C++ destructor in the class definition.

This approach is only possible because the Java representative instances are stateless. With the exception of their C++ object handles, they do not contain any member variables that could be assigned to different values.

However, in order to remove a C++ object that is allocated as a result of using the new operator on a wrapping Java object, the delete method must be called. This is due to a GlobalReference kept in the JNI code that prevents the garbage collector from running.

Inheritance Methods

Chapter 1. C++ Access Builder 5 Member variables Operators Global definitions Pointers References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ Services: overview Methods The generated Java class contains all the public methods found in the C++ object. The method in the Java class calls a corresponding native method in the C++ wrapper. The native method then forwards the call to the method on the matching C++ object.

Static C++ methods are mapped to static methods in Java. This also means that the containing class does not need to be instantiated in order to call a static method.

In the following example, assume that a class named A contains two methods: static void M(int); void M(char *);

In Java, you can access these two methods as follows:

A x = new A(); A.M(50); PCHAR y = new PCHAR(“Hello”); x.M(y);

Note that for the static method void M(int), the generated code in the wrapper function does not require an instance of class A to be created in advance.

Constructors and destructors Inheritance Member variables Operators Global definitions Pointers References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

6 C++ Access Builder Accessing C++ services: overview Member variables Member variables of C++ classes are made accessible through a pair of access methods in the Java class. Consider the following C++ member variable: ;

The following two methods are generated for the C++ member variable: get(); void set();

If a C++ member variable is declared constant, the set method is not generated.

In the following example, assume that a C++ class A contains two public member variables: const int Foo; static int Bar;

In Java, you would access these C++ member variables as follows: A x = new A(); int fooValue, barValue;

x.setBar(10); fooValue = x.getFoo(); barValue = x.getBar();

When the C++ member variable is a pointer, the C++ Access Builder requires the C++ library to allocate the memory to which the pointer points. When performing a set on a C++ character string, be careful to ensure that enough memory has been allocated, otherwise unpredictable results will occur.

Array Types Array type member variables are handled differently than other member variables. The C++ Access Builder generates access method pairs (get, set) on the level of array elements. This allows you to deploy a uniform mapping scheme for all array type variables of arbitrary dimension. For example, assume that you have an n-dimensional array of a certain C++ base type: [d1] ... [dn];

In this case, the following mapping is applied: get (int d1, ..., int dn); void set (int d1, ..., int dn, elem);

You can use the method int Length() to return the number of elements of the array. However, if the array is a static member variable, or if it is a global variable, the number of elements cannot be determined, and the function Length will return -1. Additionally, a warning will be written into the log file signalling that the size of the array could not be determined.

For array type variables declared as constant, the set function is not generated (just like regular member variables).

Chapter 1. C++ Access Builder 7 You are still responsible for ensuring that their array indices stay within a valid range. There are no range checks applied automatically by the generated wrapper code.

Consider the following C++ definition: typedef char str[5];

class A { public: str myArray[10]; };

In Java, you would access it as follows: A x = new A(); x.setmyArray(1,1,'a');

Constructors and destructors Inheritance Methods Operators Global definitions Pointers References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Operators Operator overloading In C++, the following operators cannot be overloaded: v The scope resolution operator (::) v The pointer to member operator (.* ) v The class member access operator (.) v The conditional expression operator (?:) Aside from the above operators, the C++ Access Builder maps all publicly defined member definitions of overloaded C++ operators to Java methods which have a special name. The notation capabilities, such as infix or postfix notation, of the particular operator are lost, but the operator definitions remain accessible through access methods. The names of the operator access methods contained in the Java representative class are created using the following naming conventions: operator () to Operator_ ()

The program maps C++ operator signs to special names in Java which become part of the access method name. It distinguishes between postfix and prefix versions of

8 C++ Access Builder the increment and decrement operators are distinguished. The following table shows the mapping of C++ operator signs to their corresponding Java names:

C++ Operator Java Representation C++ Operator Java Representation + PLUS != NEQ - MINUS && AND *MULT||OR * PTR << SHL / DIV >> SHR % MOD -= MINUSASSIGN | BXOR /= DIVASSIGN & BAND %= MODASSIGN & ADR += PLUSASSIGN | BOR |= BXORASSIGN x BNOT &= BANDASSIGN ! NOT |= BORASSIGN , COMMA *= MULTASSIGN = ASSIGN <<= SHLASSIGN < LT >>= SHRASSIGN > GT [ ] INDEX <= LE ( ) FUNCCALL >= GE == EQ ++ POSTINCR — POSTDECR ++ PREINCR — PREDECR

The C++ Access Builder uses the signatures of the C++ operator definitions to generate appropriate C++ wrapper code. It recognizes six classes of C++ operators are by their names and signatures: v N-ary operators: the function call operator () v Binary operators: +, -, *, /, %, |, &, |, comma(,), /, =, <, >, <=, >=, =, ==, !=, &&, ||, >>, +=, >>, -=, /= , %=, |=, &=, |=, *=, >>=, <<= v Unary prefix operators: +, -, *, &, x, !, the prefix increment operator ++, and the prefix decrement operator — v Unary postfix operators: the postfix increment operator ++ and the postfix decrement operator — v The index operator [] v The new operator For example, consider the following C++ definition: class cClass { public: cClass(int i); cClass operator+ (cClass i); // member operator friend cClass operator- (cClass a, cClass b); private: int x; }

cClass operator- (cClass a, cClass b); // non member operator

Chapter 1. C++ Access Builder 9 In Java, you would access it as follows: cClass x = new cClass(0); cClass y = new cClass(10); cClass z = new cClass(20); x = y.Operator_PLUS(z); // member operator

x = Statics.Operator_PLUS(y,z); // non member operator

Note that the nonmember operator is placed in a class called Statics, along with all global variables, methods, and operators. To use the nonmember operator, you do not need to create an instance of Statics, because the nonmember operator is global and not part of any C++ class. You can find additional information about globals in the topic “Global Definitions”.

Operator new The only operator that does not conform to the usual mapping scheme is the operator new. If the operator new is overloaded and requires additional parameters other than the mandatory parameter of type size_t, which contains the size of the memory buffer to be allocated, the additional placement parameters must be passed whenever new is used to create a class instance. Once the memory for the class object is allocated, the class constructor is called according to the constructor version specified after new. The general C++ syntax is: new [()] ([])

The placement parameters must be omitted if a version of new is to be used that only requires the size parameter. An arbitrary number of definitions for the operator new can be specified as long as each definition has a unique signature.

The C++ Access Builder combines the C++ class constructors with the operator new in a set of Java constructors. The parameters of these constructors are used to pass both the placement parameters and the constructor parameters. For this purpose, an additional class named com.ibm.ivj.eab.j2cpp.__PlacementDelimiter_ is introduced. This class serves as a delimiter between the placement parameters and the constructor parameters. This delimiter is necessary since there might be combinations in which this distinction is not always possible. This implies that for n C++ constructors and m new operator definitions, m*n Java constructors are generated.

Note that you must include stddef.h in your definition file if you are using any variables or methods which use the type size_t.

The following example shows a C++ class that provides two constructor versions and two versions of the operator new: A() A(int, int) void *operator new(size_t); void *operator new(size_t, int, int);

In Java, you can invoke the constructors as follows: // Use the first new operator A a = new A(); A b = new A(1,2);

// Use the second new operator using '3' and '4' as // the placement parameters A c = new A(3,4,(__PlacementDelimiter_)NULL); A = new A(3,4,(__PlacementDelimiter_)NULL,1,2);

10 C++ Access Builder Operator delete The delete operator can be overloaded only by using void * as the first argument and size_t as an optional second argument. Regardless of the actual signature, the delete operator is always used in the normal manner, as in delete . It is called by the generated Java finalize routines, which are bound to the Java garbage collector. This means that the C++ wrapper layer uses the delete operator transparently in the same way, whether it is overloaded or not. If there is a definition of the delete operator for the class of the object to be deleted, its implementation is called rather than the default implementation ::delete.

Member selection operators The C++ Access Builder ignores the member selection operators -> and ->*. The operator -> (member selection) and ->* (pointer to member selection) cannot be mapped to Java because of their special semantics.

Constructors and destructors Inheritance Methods Member variables Global definitions Pointers References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Global definitions The C++ Access Builder also maps C++ definitions that do not belong to a particular C++ class. It accomplishes mapping by introducing an additional Java representative class named Statics. This class serves as a container for any Java access methods that represent globally defined functions, variables, or nonmember operators. This mapping is similar to the mapping procedures described for class members. The only difference is that all Java access methods are defined as static. There is no need to instantiate the implicit container class Statics, so no constructor or finalize method is required.

The signature mangling is only applied to nonmember operators since they can have polymorphic versions. The wrapper layer for these Java access methods forwards the calls to the nonmember definitions provided by the C++ definition files.

The ability of the C++ Access Builder to map static definitions means that it can also generate interfacing code for normal C libraries. In this case, only one Java class is generated that maps the procedural C code to the object-oriented Java code.

Chapter 1. C++ Access Builder 11 In the following example, assume that a definition file has the following global definitions: extern unsigned int j;

extern int x;

extern int getVal();

void setVal(int y);

char* ret_String(char* str1, int a, unsigned long b);

extern int a1[];

(Note that the functions are extern by default. When importing a set of definition files, you must ensure that there is only one instance of an extern variable. Otherwise, duplicate methods to get and set the variable will be generated, which will result in compile errors.)

In Java, you can access the variables and methods as follows:

// Access unsigned int j UINT ua = new UINT((long)25); // Note that casting to long is required. Statics.setj(ua); UINT ub = new UINT(); ub = Statics.getj();

// Access int x Statics.setx(30); Statics s = new Statics(); // Note that you do not have to create an instance. int i = s.getx();

// Use methods getVal and setVal i = s.getVal(); Statics.setVal(i);

// Use method ret_String ULONG ul1 = new ULONG((long)30); PCHAR b_char = new PCHAR(“Hello”); PCHAR a_char = Statics.ret_String(b_char,(int) 5, ul1); String a_string = new String(a_char.value);

// Access the elements of array int a[1] int index; for(index=0;index<5;index++) { Statics.seta1(index,3); } for(index=0;index<5;index++) { System.out.println(“Value from int array index ”+index+“ is ”+Statics.geta1(index)); }

Constructors and destructors Inheritance Methods Member variables Operators Pointers References Unions and enums

12 C++ Access Builder Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Pointers There are twelve base pointer classes provided by the C++ Access Builder run-time class library. For information about these base classes, see the information on IBM APIs in the Reference online help. When the C++ Access Builder encounters a pointer to a class other than these base classes, it will wrap the class with a Java class. The name of this Java class will be PointerToCLASS_.

If the C++ Access Builder has already parsed the pointer’s class definition before encountering the pointer, then the Java class provides full access to the public methods and data members of the class that the pointer points to. If the pointer’s class definition has not been encountered before the pointer, then the Java class provides an opaque pointer to the corresponding C++ object. The public methods and data members of the C++ object cannot be accessed. However, the pointer to the C++ object can still be passed as a parameter to methods.

The C++ Access Builder also generates an opaque pointer if it encounters a pointer to a pointer (char **var, for example). Similarly, the C++ Access Builder generates an opaque pointer if it encounters a reference to a pointer (char*&, for example).

In the following example, consider a definition file that contains the following elements: class xClass;

class yClass { public: yClass();

xClass* getX(); void setX(xClass* p1);

private: xClass* p; };

The definition file results in the generation of a class named PointerToCLASS_xClass. This class can be used as follows: yClass a = new yClass(); PointerToCLASS_xClass b = a.getX(); a.setX(b);

Assume that the definition file had defined xClass as follows: class xClass { public: xClass();

int getInt(); };

class yClass {

Chapter 1. C++ Access Builder 13 public: yClass();

xClass* getX(); void setX(xClass* p1);

private: xClass* p; };

In this case, you can use the generated Java class PointerToCLASS_xClass as follows: yClass a = new yClass(); PointerToCLASS_xClass b = a.getX(); int c = b.getInt();

Constructors and destructors Inheritance Methods Member variables Operators Global definitions References Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview References There are twelve base reference classes provided by the C++ Access Builder class library. For information about these base classes, see the information on IBM APIs in the Reference online help. When the C++ Access Builder encounters a reference to a class other than these base classes, it may wrap the class with a Java class. The name of this Java class will be ReferenceToCLASS_.

If the C++ Access Builder has already parsed the class definition for the reference before encountering the reference, then the generated .java class provides full access to the public methods and data members of the class that the reference points to. The generated C++ wrapper handles any differences in passing by value and passing by reference. If the reference’s class definition has not been encountered before the reference, then the ReferenceToCLASS_.java class is generated and provides an opaque pointer to the corresponding C++ object. The public methods and data members of the C++ object cannot be accessed. However, the pointer to the C++ object can still be passed as a parameter to methods.

In the following example, consider a definition file that contains the following elements: class xClass;

class yClass {

14 C++ Access Builder public: yClass();

xClass& getX(); void setX(xClass& p1);

private: xClass p; };

In this case, a Java class is generated named ReferenceToCLASS_xClass. This class can be used in the following manner: yClass a = new yClass(); ReferenceToCLASS_xClass b = a.getX(); a.setX(b);

Assume that the definition file had defined xClass as follows: class xClass { public: xClass();

int getInt(); };

class yClass { public: yClass();

xClass& getX(); void setX(xClass& p1);

private: xp; };

In this case, you can use the generated Java class xClass as follows: yClass a = new yClass(); xClass xRef = a.getX(); int c = xRef.getInt();

Constructors and destructors Inheritance Methods Member variables Operators Global definitions Pointers Unions and enums Conversion functions Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview

Chapter 1. C++ Access Builder 15 Unions and enums Any wrapped union or enum is wrapped as an opaque object. This means that from a Java client, you can only receive a union or enum as a returned object or pass it as a parameter. The Java client cannot construct a union or an enum, or access its value. A union can have the following names in Java, depending on whether it is a pointer, reference, or value:

PointerToUNION_ ReferenceToUNION_ UNION_

Enums are handled differently than unions because the enumerator may be part of a class or a global definition. If an enum is part of a class, then the name in Java is:

PointerToENUM___ ReferenceToENUM___ ENUM___

If an enum is not part of a class, then the name in Java is:

PointerToENUM_ ReferenceToENUM_ ENUM_

For example, assume that a definition file contains the following elements: enum mybits {firstbit=0, secondbit=2, lastbit=4};

class yClass { public: yClass();

mybits& getEnum(); void fooEnum(mybits& r1);

};

This results in the generation of two enum Java classes named ENUM_mybits and ReferenceToENUM_mybits. You can use the ReferenceToENUM_mybits class in the following manner: yClass a = new yClass(); ReferenceToENUM_mybits b = a.getEnum(); a.fooEnum(b);

Constructors and destructors Inheritance Methods Member variables Operators Global definitions Pointers References Conversion functions Type conversion

16 C++ Access Builder C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Conversion functions Conversion functions, or so-called cast operators, can also be mapped by the C++ Access Builder. The names of the cast operator access methods contained in the Java representative class are created using the following naming conventions: operator (); to operatorCAST_ ();

In this example, the type is either a specific built-in, derived (pointer), or a class . You cannot specify an argument list or a return type, and you must specify any conversion functions as member functions.

The C++ Access Builder maps these conversion functions to methods of the Java representative class. It derives the name of the represntative class from the target type of the conversion function. The naming scheme it applies for C++ types is shown in the following table:

C++ type Java name C++ type Java name void VOID long LONG char CHAR unsigned long ULONG unsigned char UCHAR signed long LONG signed char SCHAR float FLOAT wchar_t WCHAR short SHORT double DOUBLE unsigned short USHORT signed short SHORT int INT unsigned int UINT signed int INT const C++_type Const class UserDefinedClass UserDefinedClass * C++_ type PointerToCLASS_ enum UserDefinedEnum UserDefinedEnum & C++_ type ReferenceToCLASS_struct UserDefinedStruct UserDefinedStruct * UserDefinedClass PointerToCLASS_UserDefinedClassunion UserDefinedUnion UserDefinedUnion & UserDefinedClass ReferenceToCLASS_UserDefined Class

In the following example, assume a new class is defined as follows: class smallNumber { public:

smallNumber(){v=0;} smallNumber(int i) { assign(i); } smallNumber(const smallNumber& t){v=t.v; }

Chapter 1. C++ Access Builder 17 smallNumber& operator=(const smallNumber& t){v=t.v; return *this; } int value() {return v;} tj2cca01& operator=(long i) { assign(i); return *this; } // long operator long() {return (long)v;} // Cast to a long operator const int(); // Cast to const integer operator int*(); // Cast to integer pointer operator ParmClass(); // Cast to class ParmClass operator ParmClass*(); // Cast to class ParmClass pointer private: int v; // Small number between 0 and 63 void assign(int i); };

void smallNumber::assign(int i){ if (i&|63) i=0; // Outside of range. Change to 0 v=i; };

In Java, you could cast the type smallNumber to a long in the following way: smallNumber a = new smallNumber(20); long b = a.operatorCAST_LONG(); int c = a.operatorCAST_ConstINT(); int *d = a.operatorCAST_PointerToINT(); ParmClass e = a.operatorCAST_ParmClass(); ParmClass *e = a.operatorCAST_PointerToCLASS_ParmClass();

Constructors and destructors Inheritance Methods Member variables Operators Global definitions Pointers References Unions and enums Type conversion C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview Type conversion To understand the type conversion rules applied by the C++ Access Builder, you need to distinguish among five different cases: v C++ types that have a direct representation in Java. (These are primitive types such as char, int, and one-dimensional arrays of primitive types.) v C++ types for which no direct mapping exists, such as unions or pointers to unknown structures or classes. (These types are represented opaquely in Java as type int (their address).) v C++ objects, and references to C++ objects, which are known to the C++ Access Builder but have no direct representation in Java. (These types, such as unsigned int and signed char, get mapped to a Java representative class.)

18 C++ Access Builder v C++ objects, and references to C++ objects, which are not known to the C++ Access Builder and must be accessed through their opaque representation in Java. v Pointers to C++ objects. (If the C++ object is known to the C++ Access Builder, then the PointerToCLASS_ Java object can access the public data members and methods of the C++ object. If the C++ object is not known to the C++ Access Builder, the C++ object is represented opaquely in the Java object.) The following table shows how the C++ Access Builder maps C++ types from Java types.

C++ Type Java Type C++ Type Java Type Simple Types Corresponding Type References Corresponding Type char char &char class RCHAR short short &unsigned char class RUCHAR int int &signed char class RSCHAR long long &unsigned short class RUSHORT float float &short class RSHORT double double &unsigned int class RUINT void void &int class RINT Transparent Types Corresponding Type &unsigned long class RULONG wchar_t class WCHAR &long class RLONG unsigned short class USHORT &wchar_t class RWCHAR unsigned char class UCHAR &float class RFLOAT signed char class SCHAR &double class RDOUBLE unsigned int class UINT reference to known class n class n unsigned long class ULONG reference to unknown class class n ReferenceToCLASS_n Composite Types Corresponding Type Arrays Corresponding Type known struct n class n wchar_t[] WCHAR[] unknown struct n class STRUCT_n char[] char[] known class n class n signed char[] SCHAR[] unknown class n class CLASS_n unsigned char[] UCHAR[] union n class UNION _n short[] short[] In a class. enum n class ENUM___n Not in a class. enum class ENUM_n int[] int[] n Pointers Corresponding Type unsigned int[] UINT[] wchar_t* class PWCHAR long[] long[] char * class PCHAR unsigned long[] ULONG[] unsigned char * class PUCHAR float[] float[] signed char * class PSCHAR double[] double[] unsigned short * class PUSHORT class n[] class n[]

Chapter 1. C++ Access Builder 19 C++ Type Java Type C++ Type Java Type short * class PSHORT Two-Dimensional Corresponding Type Arrays unsigned int * class PUINT C++ simple_type[][] Java_simple_type[][] int * class PINT C++ Java_representative_ transparent_type[][] class[][] unsigned long * class PULONG C++ composite_type[][] Java_corresponding_ type[][] long * class PLONG float * class PFLOAT double * class PDOUBLE class *n class PointerToCLASS_n

Constructors and destructors Inheritance Methods Member variables Operators Global definitions Pointers References Unions and enums Conversion functions C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Accessing C++ services: overview

Design Considerations with the C++ Access Builder

Business logic You should consider the following points in writing any new or additional business logic to supplement or facilitate code generated by the C++ Access Builder: v Consult the “C++ Access Builder limitations” topic for information on limitations. By understanding the limitations, you can create simple and effective interfaces that provide C++ access through Java. v Consult the topic “Elements used in mapping Java to C++” for examples of how to map different C++ types from Java. v If you are working with an existing C++ library, examine the class interface for C++ data types. If there are any types that are not in the following list, you may need to write a helper function in C++ to allow for the creation of a reference for those special types. Some useful C++ types that provide the easiest translation to Java types are:

20 C++ Access Builder – Simple types, such as char, unsigned char, short, int, long, float, double, void, and enum – Class type – Simple typedef’d names redefining simple types – Pointer types, such as char* and unsigned char* – Arrays such as single-dimension arrays of char, unsigned char, short, int, long, float, and double. – Structs, which are treated as a class type. v If you are developing a new C++ interface that you will import with the C++ Access Builder and use to access an existing C++ program object, design the C++ interface so that only the primitive data types named in the above list are directly used in an interface. On the Java side of your application, these data types can help minimize the effort required to create helper classes to fields residing in complex structures. v You can use opaque structures that are passed in and out of the C++ interface, but only if the structures are carried around in the Java-side object for context association only, and the Java-side user does not intend to access fields inside those opaque structures. v You may find it helpful to create C++ header files that contain interfaces to an existing shared library. You can then use the C++ Access Builder to wrap the header files, and then create an intermediate shared library to access the existing shared library. This thin C++ interface layer would make use of the defines provided by a legacy C++ server interface for accessing the legacy C++ server. Some customization could be done in the intermediate library to take advantage of any C++ macros defined for use with the C++ server interface, which would otherwise be inaccessible from the Java programming environment. Customization may also result in a smaller interface with more loosely coupled error handling.

Error handling between Java and C++ cannot be tightly integrated because of the differences in the environments. With an intermediate shared library, error handling on the C++ side can be handled by the layer with more tightly-coupled control. v Macro defines are usable only on the C++ side. You may need to redefine equivalent information on the Java side if you want your Java program to be more readable. For example, if you originally have constants on the C++ side using the #define macro, then you will need to redefine the constants in Java if you want to use names to represent the constant. v If your legacy C++ server interface uses multiple inheritance, you will not be able to directly use the C++ Access Builder without a workaround. To implement the workaround, create a wrapper class that owns an instance of the object that is multiply inherited. The wrapper class can be defined to expose all inherited public members of the legacy interface using a different name. With this arrangement, you can import the wrapper class definition using the C++ Access Builder and then work with only the wrapper class interface. This workaround is suitable if you need to access the interface of the most derived object.

Wrapper classes Memory allocation C++ Access Builder: overview C++ Access Builder limitations

Chapter 1. C++ Access Builder 21 Accessing C++ services: overview Creating C++ header files for interfaces Wrapper classes Because of limitations with the C++ Access Builder, many header files of existing C++ libraries cannot be parsed. In these cases, a wrapper class should be created to access the interfaces of the C++ libraries. In fact, it is generally good practice to create a wrapper class to access existing C++ libraries. You can create C++ header files that contain interfaces to an existing shared library. Use the C++ Access Builder to wrap the header files, and then create an intermediate shared library to access the existing shared library.

Specifically, the wrapper class is used to accomplish the following tasks: v Map complex types to simple supported types. For example, the IString.hpp file cannot be parsed. This means that you cannot use the IString class as an argument in the interface to a C++ library. Instead, you can use a wrapper class to map IString to a char *. v Allow an existing C++ library to be accessed without rebuilding it. For instance, you can build a library which is comprised of the wrapper class. When the wrapper library is linked, you can specify the C++ library to be accessed. This allows Java code to access the existing library through the wrapper library. v Change the structure of how files are included. The wrapper class definition file should not have any #include statements. The #include statements should reside in the implementation file. These #include statements should precede the #include of the definition file. When working with wrapper classes, you should observe the following recommendations: v Only wrap those classes and methods that you actually need to access. v While you can generate multiple wrapper files into the same Java package, you should avoid running the C++ Access Builder more than once on a Java package. This will reduce your chances of accidentally overwriting generated files. v When accessing C functions, you may need to define the linkage specification of the C function in the definition file. The generated C++ wrapper file assumes the default C++ linkage specification for a function. If the function requires other linkage, such as __stdcall or __cdecl, then this must be specified as part of the function prototype in the definition file. Unless you actually require includes in your definition file, you should omit them from the file. All included header files are preprocessed and parsed, even if they are not imported because they are not found in the J2CPP_CLASSPATH. If you require access to an unparseable header file, then include it in the implementation file and map any of its classes or types to recognized types such as char *.

For example, assume that you have a C++ library with the following interface: C++ library interface rlEstLst.hpp #include class realEstateListing { private: IString oname; IString oaddress; IString aName;

22 C++ Access Builder unsigned long aId; float askingPrice; float sellingPrice;

public: realEstateListing(); void setOwner(IString name, IString address); IString ownerName(); IString ownerAddress();

void setAgent(IString name, unsigned long id); IString agentName(); unsigned long agentId();

void setAskingPrice(float value); void setSellingPrice(float value); }; rlEstLst.cpp #include “rlestlst.hpp” realEstateListing::realEstateListing() : oname(NULL), oaddress(NULL), aName(NULL), aId(0), askingPrice(100000), sellingPrice(0) { } void realEstateListing::setOwner(IString name, IString address) { oname = name; oaddress = address; } IString realEstateListing::ownerName() { return oname; } IString realEstateListing::ownerAddress() { return oaddress; } void realEstateListing::setAgent(IString name, unsigned long id) { aName = name; aId = id; } IString realEstateListing::agentName() { return aName; } unsigned long realEstateListing::agentId() { return aId; } void realEstateListing::setAskingPrice(float value) { askingPrice = value; } void realEstateListing::setSellingPrice(float value) { sellingPrice = value; }

Given the above interface to a C++ library, you could wrap it as follows: Wrap interface wrapdemo.hpp // Note that there are no includes in the definition file. class wrapDemo{ private: void* listing; public: wrapDemo(); xwrapDemo(); void setOwner(char* name, char* address); char* ownerName(); char* ownerAddress(); void setAgent(char* name, unsigned long id); char* agentName();

Chapter 1. C++ Access Builder 23 unsigned long agentId(); void setAsking(float value); void setSelling(float value); };

wrapdemo.cpp // Note that the includes are in the implementation file. #include #include “rlEstLst.hpp” #include “wrapdemo.hpp” wrapDemo::wrapDemo() { realEstateListing* rel = new realEstateListing(); listing = (void *)rel; } wrapDemo::xwrapDemo() { delete (realEstateListing*) listing; } // See how char* is changed to an IString. void wrapDemo::setOwner(char* name, char* address) { ((realEstateListing *)listing)->setOwner(IString(name),IString(address)); } // See how an IString is cast to char*. char* wrapDemo::ownerName() { return ((char *) ((realEstateListing *)listing)->ownerName()); } char* wrapDemo::ownerAddress() { return ((char *) ((realEstateListing *)listing)->ownerAddress()); } void wrapDemo::setAgent(char* name, unsigned long id) { ((realEstateListing *)listing)->setAgent(IString(name),id); } char* wrapDemo::agentName() { return ((char *) ((realEstateListing *)listing)->agentName()); } unsigned long wrapDemo::agentId() { return (((realEstateListing *)listing)->agentId()); } void wrapDemo::setAsking(float value) { ((realEstateListing *)listing)->setAskingPrice(value); } void wrapDemo::setSelling(float value) { ((realEstateListing *)listing)->setSellingPrice(value); }

Business logic Memory allocation C++ Access Builder: overview C++ Access Builder limitations

Accessing C++ services: overview Creating C++ header files for interfaces Memory allocation Creating and deleting objects From the perspective of the C++ Access Builder, there are generally two ways to allocate a C++ object: v Using the operator new in the Java code v Using the operator new in the C++ code

24 C++ Access Builder For example, if you wrap a C++ object named Rectengle, then the following Java code will create a Java object named Rectengle that points to the corresponding C++ object: Rectengle r1 = new Rectengle();

When the Java object no longer has any references, it is collected by the garbage collector. However, in order to remove a C++ object that is allocated as a result of using the new operator on a wrapping Java object, the delete method must be called:

Rectengle r1 = new Rectengle(); GenShape gs = GenShape(r1); r1.delete();

When the C++ object is created on the C++ side and returned to Java, the C++ object is, by default, not deleted when its matching Java object is garbage collected. The following Java code shows how a Java object can point to a C++ object that was allocated: Rectengle r2; GenShape gs = GenShape(); gs.genRectengle(r2);

When r2 is garbage collected, the C++ object that it points to is not deleted. This is because Rectengle was allocated on the C++ side.

You can, however, override these default actions. For example, if a C++ library allocates a C++ object and returns it to an application, and that application is required to delete the C++ object when it is no longer needed, then the default behaviour must be modified.

With the exception of opaque objects, each Java object that wraps a C++ object has two methods: public void EnableCDestructor(); public void DisableCDestructor();

In the Rectengle example above, if you require the matching C++ object to be deleted when r2 is garbage collected, then you would use the following Java code: Rectengle r2; GenShape gs = GenShape(); gs.genRectengle(r2); r2.EnableCDestructor();

Java and C++ object pairings If you use the new operator to create a Java object, then the object’s pairing with a matching C++ object is tracked. Consider the following example: Rectengle r1 = new Rectengle(); Rectengle r2; GenShape gs = GenShape(r1); r2 = gs.getRectengle();

If the wrapped C++ code of gs.getRectengle returns the C++ object mapped to by r1, then the Java object that is pointed to by r1 is also what is pointed to by r2. This maintains a 1:1 mapping between the Java object and the C++ object. When the Java object loses all of its references and is garbage collected, the C++ object is deleted.

Chapter 1. C++ Access Builder 25 If the C++ object is created in C++, a 1:1 mapping is not maintained. Whenever the C++ object is passed to Java, a new wrapping Java object is created. When this Java object is deleted, it does not affect the life of the C++ object. The C++ library must clean up the C++ object, and the Java code must not access the C++ object after it has been cleaned up.

If this default behavior is overridden as described above, the state of the mapping is not changed. For this reason, many Java objects can refer to a single C++ object. When a single Java object that enables the deletion of a C++ object can no longer be referenced, none of the other Java objects which refer to this C++ object should be used. This is because the C++ object will be deleted during garbage collection.

Business logic Wrapper classes C++ Access Builder: overview C++ Access Builder limitations

Accessing C++ services: overview

Classes generated by the C++ Access Builder The C++ Access Builder generates code that enables your Java program to access C++ services. This code includes access beans and C++ wrapper files. For each C++ class declared in your header file, an access bean and a C++ wrapper file is generated. The access bean serves as a Java stub between your Java program and the C++ wrapper file. The C++ wrapper file is used to wrapper the C++ class implementation.

The name of each access bean is the same as the name of the corresponding class declared in the header file. For instance, if a header file declares two classes named myClass1 and myClass2, then the C++ Access Builder generates two corresponding access beans named myClass1.java and myClass2.java.

Similarly, the name of each C++ wrapper file uses the name of the corresponding class declared in the header file as a name prefix. For example, if a header file declares two classes named myClass1 and MyClass2, then the C++ Access Builder generates two corresponding C++ wrapper files named myClass1Wrapper.cpp and myClass2Wrapper.cpp.

The C++ Access Builder also generates a makefile. The makefile automatically builds a library that enables C++ classes to be accessed as native methods.

Essentially, the only code you need to provide yourself is: v The definitions of C++ server objects in the form of C++ header files v The implementations in the form of C++ source files v The Java client source code The C++ Access Builder generates everything else. The following figure shows the relationship between the source code and the code generated by the C++ Access Builder.

26 C++ Access Builder Code generated by the C++ Access Builder For each class declared in a specified header file, the C++ Access Builder generates the following code:

Generated Code Description class.java Contains the Java representative bean through which C++ code is accessed. classWrapper.cpp Contains intermediate code that builds the bridge between Java and C++. Its code consists of functions called by the Java run-time system which then invoke the C++ class implementation.

For each global definition declared in a specified header file, the C++ Access Builder generates the following code:

Generated Code Description Statics.java Contains the special Java representative class Statics. This class contains Java access methods for each C++ declaration that was not part of any C++ class. All of its methods are declared static. As a result, the Java representative class Statics does not need to be instantiated before its methods can be used.

Chapter 1. C++ Access Builder 27 StaticsWrapper.cpp Contains the C++ wrapper code for the Java class Statics.

Code generated by the makefile The C++ Access Builder generates a makefile, libname.mk, for the specified C++ compiler. When run, the makefile generates a system-specific library so that the generated C++ wrapper code can be called as a native method. The name of the shared library and other library files is whatever name you specify when you run the C++ Access Builder.

Note that Java can only use native code provided as a shared library.

When the makefile is run, the following code is created:

Generated Code Description sharedlib.lib Shared library file. sharedlib.dll Dynamic link library file. sharedlib.exp Export file on Windows® 95 and NT.

On the Windows operating systems, a DLL (.dll) is needed. For this reason, the makefile generates a definition file (.def) as part of the build by using the CPPFILT utility.

On Windows operating systems, an export file (.exp) can be generated by using the VisualAge C++ ilib tool.

Each class that contains native method definitions must have a static section in which the library is loaded. The code in the static section is executed before the constructor is called. This technique ensures that all native method definitions get assigned with the corresponding code in the library. Through their static sections, the generated Java classes will be associated with a library of this name.

Note that the fact that the library is loaded before the object is instantiated has important implications. For instance, if you try to introspect the generated Java bean, it fails unless the shared library is available for loading. Therefore, the shared library should generally be built prior to coding the client.

C++ Access Builder: overview C++ Access Builder limitations

Accessing C++ services: overview Creating C++ header files for interfaces Generating C++ access beans and wrapper files Creating a shared library

Makefile targets

28 C++ Access Builder C++ Access Builder limitations When using the C++ Access Builder, you should consider the following limitations:

No support There is no support for the following: v Object serialization. If you require object serialization, you will need to wrap the generated Java classes and provide an interface that supports serialization. v Multiple inheritance. v Templates. v Default arguments in method calls. You must supply the default values as the call is made on the Java side. v Parsing of files that contain incorrect syntax. You can only parse files that are syntactically correct. You may get unpredictable results if your source files contain syntax errors. v Nested class definitions or typedefs. More specifically, there is no support for class definitions or typedefs within a class definition. v Inheritance across the Java/C++ boundary. You cannot invoke protected methods and there is no programming model for abstract base classes. v Direct access to data members. You must use accessor methods. v 3-dimensional arrays or larger are not supported when passed as parameters. Limited support There is limited support for the following: v Function/operator overload as a result of type folding. Functions in C++ that are recognized as having different signatures may be translated to the same signature due to type folding. v Array syntax for 2-dimensional arrays passed as an argument. Consider the following syntax:

type x[][num] /* This works */ type* x[num] /* This works */ type x[num][num] /* This does not work */

v Function bodies or method bodies. Function bodies or method bodies should be excluded from definition files that will be processed by the C++ Access Builder. v Expressions. Any expressions should be excluded from definition files that will be processed by the C++ Access Builder. Compiler support For the following limitations, support exists for any C/C++ compiler, but certain conditions must be met: v The output of the preprocessor must be directed to stdout. v The preprocessor output must contain #line statements. v The preprocessor must handle your files as C++ files or the definition file must specify the linkage of each function. v Any #pragma support will be compiler-specific. A list of pragma values must be provided to the parser so that they can be skipped. v If the C/C++ compiler stores the first data member at the same address as that of its object, and the data member is public, then incorrect results can occur if

Chapter 1. C++ Access Builder 29 you use the accessor methods for the data member. To avoid this problem, you can declare a dummy protected or private data member as the first data member of the object. Miscellaneous v Only one instance of each extern can exist in the list of class definition files specified in the C++ Access Builder SmartGuide. v Java packages should be scoped to directly access only one C++ library. If this is not done, there is the possibility that generated files will be overwritten. For instance, if two libraries are imported into the same package and both libraries contain globals, then the Statics files will be overwritten. v The IDE VM implements floats using doubles. If you wrap a float and try to perform comparisons in Java, there may be precision inaccuracies. v Some definition files cannot be imported if they contain definitions that the C++ Access Builder cannot parse. These definition files can usually be wrapped by another definition file which can be imported. v If you need to rename the package containing your generated Java access beans, you must use the C++ Access Builder to regenerate the code and specify the new package name.

C++ Access Builder: overview

Accessing C++ services: overview

30 C++ Access Builder Chapter 2. Using the C++ Access Builder

Accessing C++ services: overview The C++ Access Builder generates access beans and associated classes that enable your Java program to access C++ services. You can use the C++ Access Builder SmartGuide to generate your code and develop your application in the Visual Composition Editor. You must have the JDK 1.2.2 and a C++ compiler installed and configured.

To enable your Java program to access C++ services: 1. Create the package.

If necessary, create a package to contain the access beans generated by the C++ Access Builder. 2. Create C++ header files for the interfaces.

If you have no C++ header files that contain interfaces to your shared library, create one or more header files for the interfaces that you want to expose. If you already have header files, but they cannot be parsed because of C++ Access Builder limitations, you may need to create new header files to wrap the interfaces that you want to expose. 3. Generate the C++ access beans and wrapper files.

Use the C++ Access Builder to import the header files and generate the access beans, C++ wrapper files, and a makefile used for building the C++ shared library. You can use the generated makefile without modification, tailor it to your needs, or use it as a template for your own makefile. The makefile is generated into the specified directory. 4. Create the shared library.

Create the shared library that you want to access from your Java program. Run thenmake command to process the makefile that builds the shared library and compiles the access beans generated by the C++ Access Builder. If a shared library already exists, processing the makefile will modify it. If no shared library already exists, processing the makefile will create a new shared library. You should then ensure that the shared library can be accessed. 5. Create the client using the C++ access beans.

In the IDE, open the Visual Composition Editor and construct your client using an access bean as a nonvisual bean. The client code is automatically compiled when you save your work and is used to access the wrappered C++ classes. Alternatively, you can use an editor to construct the client and compile the client code from the command line using the javac command. 6. Test the application in the IDE.

Once you have created your client, use the IDE to test run your client from program main. 7. Deploy the application.

© Copyright IBM Corp. 1997, 2000 31 Package and deploy your application and start your client as a stand-alone application.

C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations Business logic Wrapper classes Memory allocation

Generating C++ access beans and wrapper files Creating a shared library

Makefile targets

32 C++ Access Builder Chapter 3. Preparing to Generate C++ Access Beans

Creating a package for C++ access beans In the IDE Workbench, you must have a package in which to store your access beans and associated classes that you generate using the C++ Access Builder. If you already have a package, follow the instructions in the topic “Create C++ header files for interfaces”. If you do not have a package, create one now by following the instructions found in the topic “Creating a package”.

You should only access one C++ shared library in each package because the C++ Access Builder may generate classes which have names that are not unique. For example, Statics is a class used to access global functions and variables in a shared library. By accessing only one shared library in each package, you ensure that no generated file will be overwritten. If from your client you want to access more than one C++ shared library, each of which has a Statics class, each Statics class can be accessed by fully qualifying it using the appropriate package name.

C++ Access Builder: overview

Creating C++ header files for interfaces Creating a package

Creating C++ header files for interfaces If you don’t have any C++ header files that contain interfaces to your C++ shared library, then you need to create one or more header files to contain the interfaces that you want to expose. The C++ Access Builder generates an access bean and a C++ wrapper file for each C++ class definition that is declared in a header file.

If you already have C++ header files that contain interfaces to your C++ shared library, but you find that the files cannot be parsed by the C++ Access Builder because of its limitations, then you may still need to create new header files for wrapping the interfaces. Limitations of the C++ Access Builder are discussed in the topic “C++ Access Builder limitations”.

Once you have created a C++ header file with interfaces to your existing C++ shared library, you can use the C++ Access Builder to generate access beans and wrapper files, and specify the shared library in the Add libraries needed for linking shared library field. The specified library will be included in the link statement for the generated shared library. You can use the generated bean to access the existing shared library.

C++ Access Builder: overview C++ Access Builder limitations

© Copyright IBM Corp. 1997, 2000 33 Generating C++ access beans and wrapper files Creating a shared library

34 C++ Access Builder Chapter 4. Generating C++ access beans and wrapper files

Use the C++ Access Builder to generate code that enables your Java program to access C++ services. The C++ Access Builder generates new Java class definitions from existing C++ class definitions contained in class definition files. For each C++ class, the C++ Access Builder generates an access bean and a C++ wrapper file. It also generates two makefiles and other files that are used to create the system-specific library required to call the generated C++ wrapper code as a native method. Java can only use native code provided as a shared library.

To generate C++ access beans and wrapper files, perform the following steps: 1. From the appropriate project in the IDE Workbench, select a named package to contain the generated code. 2. From the Selected menu, select Tools - C++ Access - Create Access Beans. The C++ Header Files page of the SmartGuide opens. 3. Beside the Add C++ header files list box, use Add to select the C++ header files containing the classes you want your Java client program to access. As you add files from the dialog box, they appear in the Add C++ header files list box. 4. Beside the Add Directories list box, use Add to select the directories containing the header files included by the header files specified above. As you add directories from the dialog box, they appear in the Add directories list box. This field is optional. 5. Click Next. The C++ Code Generation page of the SmartGuide opens. 6. In the Output directory field, type the path of the directory you want the output to be saved in. 7. In the Library name field, type the name for the generated makefile and the shared library and click Next. The C++ Compiler page of the SmartGuide opens. 8. From the Select desired compiler pull-down list, select the C++ compiler you want to use to preprocess the definition files. 9. In the Preprocessor command field, either accept the default for your compiler, or type the commands you wish to use. 10. In the Add header files include directories list box, add the directories that contain included files required for preprocessing the header files and click Next. The C++ Implementation page of the SmartGuide opens. 11. In the Add implementation C++ files field, add the C++ source files (.cpp) to be added to the makefile used to generate the shared library. 12. In the Add libraries needed field, add the shared libraries that you want to include in the link statement for the generated shared library. This field is optional.

If you are creating a wrapper class to access an existing shared library, you should add that library to this field. The existing shared library should be included (referenced by #include) in a header file specified in the Add C++ header files field on the first page of the SmartGuide. 13. Click Finish. The access beans, makefiles, and wrapper files are generated into the specified directory and Java package.

© Copyright IBM Corp. 1997, 2000 35 You can now run the makefile to generate the C++ shared library; for information on this task, see the topic, “Creating a shared library”.

C++ Access Builder: overview Classes generated by the C++ Access Builder C++ Access Builder limitations

Creating a shared library Creating C++ header files for interfaces

36 C++ Access Builder Chapter 5. Creating Shared Libraries

Creating a shared library In addition to generating access beans and C++ wrapper files, the C++ Access Builder generates two template makefiles: a master makefile and a lower-level makefile. These makefiles are used to build the required C++ shared library. If your compiler was not in the Select Desired Compiler drop down list of the SmartGuide, you will need to manually modify the template makefiles to work with your C++ compiler.

Generally, you can use the template makefiles without making any modifications. However, you may choose to tailor the makefiles to your own specifications. If you have an existing makefile of your own, you may want to simply modify it to resemble the template makefiles.

If you have an existing shared library, you can use the makefiles to build a completely new C++ shared library that contains wrapper code to access the existing shared library. Alternatively, you can use the makefiles to simply rebuild the existing shared library with wrapper code.

The name of the master makefile is Makefile. When you issue a command to run Makefile, the lower-level makefile is also run. The lower-level makefile generates a library that contains the C++ wrappers and the C++ object implementation code. The name of the library is whatever name you specify in the Library name field of the Create Access Beans and Wrapper Files SmartGuide. The generated Java wrapper file contains a statement which loads the specified library whenever the Java representative class is instantiated.

To generate the shared library using the VisualAge for C++, Version 3.0 or 3.5 compiler nmake command, just run nmake with no parameters.

The master makefile provides the following targets: nmake all clean class-files wrapper-obj-files imp-obj-files obj-files

The parameters are all optional. Only one parameter can be specified at a time. If no parameter is specified, the all parameter is specified by default. The command parameters are described in the topic, “Makefile targets”.

If you are using another C++ compiler, use the make program for that compiler. You can also build the shared library without using a makefile. For details on how to do so, see the topic, “Creating the shared library without a makefile”.

C++ Access Builder: overview C++ Access Builder limitations

© Copyright IBM Corp. 1997, 2000 37 Creating the shared library without a makefile Generating C++ access beans and wrapper files

Makefile targets

Creating a shared library without a makefile You may choose to build the shared library without using a makefile. 1. Compile all of your C++ implementation files. 2. Compile all of your C++ server wrapper files. For each C++ server class named MyClass in your application, the C++ Access Builder generates one C++ server wrapper file named MyClassWrapper.cpp. 3. Compile all of your Java server stub files. For each C++ server class named MyClass in your application, the C++ Access Builder generates one Java server stub file named MyClass.java. Other Java server stub files are also generated by the C++ Access Builder. These stub files handle things like nonmember functions. To ensure that all of the Java server stub files are compiled, do a mass compilation of all .java files. Other Java files are generated for handling such things as pointers to classes and constant references to classes. 4. Build the shared library. The name of the shared library must be the same as the one specified during the C++ header file import. The object files packaged into the shared library include all object files for your C++ server implementation and all object files for the C++ server wrappers. The shared library must link in the C++ Access Builder run-time library using ivjtjs20.lib.

C++ Access Builder: overview C++ Access Builder limitations

Generating C++ access beans and wrapper files

38 C++ Access Builder Chapter 6. Creating a client using C++ access beans

Once the C++ Access Builder has generated the access beans and associated classes and you have created the shared libraries, you are ready to create your client. 1. Assemble the client in the Visual Composition Editor. 2. Handle any exceptions. 3. Save the client code. Assemble the client in the Visual Composition Editor To assemble the client in the Visual Composition Editor: 1. Create or select a package for your client application. From the package’s popup menu, select Open To - Visual Composition. The Visual Composition Editor opens. 2. Add the access bean to the free-form surface as a nonvisual bean. On the Beans Palette, click the Choose Bean button and browse to your generated access bean. Then drop the bean on the free-form surface. 3. Connect the user interface controls of your visual client to the nonvisual bean. Handle exceptions You may choose to enable your application to handle any IVJJException exceptions thrown as a result of problems encountered by the client in making a native method call. For example, you could handle IVJJException exceptions in the following manner:

try { ... } catch( IVJJException exc ) { System.out.printIn(“Error: ” + exc.getMessage( ) ); }

Save the client code In the Visual Composition Editor, when you select Save Bean from the Bean menu, your client code is automatically compiled.

However, you can also export your classes from the IDE and compile the client from the command line using the Java Developers Kit (JDK) Version 1.2.2. If you developed the client application from the command line, then you must compile from the command line.

C++ Access Builder: overview

© Copyright IBM Corp. 1997, 2000 39 40 C++ Access Builder Chapter 7. Testing the client from program main

Once you have created your client using the access beans, you can test run your client as a stand-alone application from program main. However, you should make sure that the C++ shared libraries accessed by the application are in a directory specified in the PATH environment variable.

The C++ shared libraries accessed are the generated shared libraries and any shared library that it is linked with. This includes the C++ Access Builder run-time shared library ivjtjs20.dll.

C++ Access Builder: overview

Running an application from the IDE

© Copyright IBM Corp. 1997, 2000 41 42 C++ Access Builder Chapter 8. Deploying the client as a stand-alone application

Once you have tested your application in the IDE, you are ready to deploy your client program as a stand-alone application by performing the following activities: 1. Package and deploy your code. 2. Start your client program. Deploy your code When deploying your client program as an application, deploy your code to a directory on your client machine. This code includes the access beans that you generated using the C++ Access Builder. The directory must be accessible through the relevant environment variable on the client machine.

The source code for the stand-alone client application that is generated by the Visual Composition Editor uses the following naming convention (where AppName is the name of the application):

AppName.java

For example, if the name of the application is J2cppDemo, the name of the generated client source code file is J2cppDemo.java.

The C++ Access Builder ivjtjs20.dll run-time library, plus the C++ library and any run-time library it uses, must all be copied to a directory on the client system where you will run your application. The correct environment variables must be set to permit access to these libraries.

Generally, you need to deploy the following items: v All .class files v Client logic application and associated classes v ivj2cpp.zip file v The C++ shared libraries that the application accesses The ivj2cpp.zip file is an uncompressed zip file stored in a VisualAge for Java directory that contains all the run-time class libraries for the Enterprise Access Builders. It includes the C++ Access Builder library com.ibm.ivj.eab.j2cppaccess. The ivj2cpp.zip file path and name must be added to the system environment variables.

Additional information about the access beans and associated classes generated by the C++ Access Builder is found in the topic “Classes generated by the C++ Access Builder”. For information about the run-time classes of the C++ Access Builder class library, see the information on IBM APIs in the Reference online help.

Start your client program Once you have ensured that the C++ Access Builder run-time class library, your client application classes, and the C++ shared libraries are accessible on the client machine, you can start the client as a stand-alone application.

To start the client as a stand-alone application: 1. Ensure that you have TCP/IP and the Java Developers KIT (JDK) Version 1.2.2 installed and configured on your machine.

© Copyright IBM Corp. 1997, 2000 43 2. Issue the following command to start your client program as a stand-alone application from program main:

java packageName.ApplicationName For example: java myClientPackage.Application

C++ Access Builder: overview Classes generated by the C++ Access Builder

Exporting code Generating C++ access beans and wrapper files

44 C++ Access Builder Chapter 9. Tutorial

Sample: accessing a C++ library This sample shows you how to use the C++ Access Builder to build a Java client that accessesaCorC++library. The sample program uses an existing C++ shared library that provides a stack, which allows you to push and pop character strings and determine the number of elements in the stack. Objectives v To access an existing C++ shared library through an intermediate shared library. You do not have to recompile or relink your existing C++ shared library to gain access to it from a Java application. v To see how the C++ Access Builder run-time class library is used. The class PCHAR is used to push and pop character strings. v To develop a client program that uses a generated access bean to access an existing C++ shared library. Time required Allow 15 minutes to run the sample and 45 - 60 minutes to develop the sample. Before you begin v To develop the sample program, you must be a package group member or an administrator. v To run the sample program from the command line, you must have the JDK 1.2.2 installed and configured on your computer. Description “Running the sample program” shows you how to run the provided, ready-made sample program from the IDE. When run from the IDE, a graphical interface is provided which has an input field and button for pushing, a display field and button for popping, and a display field that displays the number of elements in the stack. This section describes the following tasks: v Adding the project to the workbench“Add the project to the workbench” on page 46 v Running the sample in the IDE“Run the sample in the IDE” on page 46 “Developing the sample program” shows you how to use the Visual Composition Editor to assemble a client interface and connect it to the StStack access bean generated by the C++ Access Builder. It also describes how to run the program. This section describes the following tasks: 1. Adding the project to the workbench“Add the project to the workbench” on page 47 2. Generating the C++ access beans and wrapper files“Generate the C++ access beans and wrapper files” on page 47 3. Creating the shared library“Create the shared library” on page 47 4. Creating the client class“Create the client class” on page 48 5. Adding the StStack bean to the Visual Composition Editor“Add the StStack bean to the Visual Composition Editor” on page 48

© Copyright IBM Corp. 1997, 2000 45 6. Creating the client program GUI“Create the client program GUI” on page 48 7. Connecting the client program GUI“Connect the client program GUI” on page 48 8. Running your sample program in the IDE“Run your sample program in the IDE” on page 49 “Running the sample program from the command line” shows you how to run the sample program from the command line. When running from the command line, the sample performs the pushes and pops and also displays the number of elements on the stack. Each time a push or pop occurs, the program displays what is pushed or popped. v Starting the sample“Start the sample” on page 50 v Running the sample as an application from the command line“Run the sample as an application from the command line” on page 50

Running the sample program To begin running the sample program, ensure that the stack and ststack shared libraries reside in a directory that is defined in your system PATH environment variable. Add the project to the workbench Open the VisualAge for Java IDE. If you have not previously added the IBM Enterprise CPP Access Builder Examples feature to the Workbench, add it using File - Quick Start. Run the sample in the IDE 1. In the com.ibm.ivj.examples.cpp package, select the StStackWindow class and click mouse button 2. This is the client program’s executable class. 2. Select Run - Check Class Path. The Properties for StStackWindow dialog opens. 3. On the Class Path tab, beside the Project Path field, click Edit. The Class Path dialog opens. 4. Ensure that the IBM Enterprise CPP Access Builder Library project is selected and click OK. 5. Click OK. 6. From the Selected menu, choose Run - Run main. The client window opens. 7. Maximize the client window as necessary. 8. In the top field, type Apples and click Push. This adds an element to the stack. 9. In the same field, type Oranges and click Push. This adds another element to the stack. 10. Click Depth. The field above the Depth button shows that there are two elements on the stack. 11. Click Pop. The field above the Pop button shows that the element Oranges has been popped off the stack. 12. Click the Depth button. The field above the Depth button now shows that there is one element on the stack. 13. Close the client window.

46 C++ Access Builder Develop the sample program The following instructions show you how to develop the client interface using the Visual Composition Editor and connect it to the access bean generated by the C++ Access Builder.

To begin developing the sample program, ensure that the stack and ststack shared libraries reside in a directory that is defined in your system PATH environment variable. Add the project to the workbench 1. Open the VisualAge for Java IDE. If you have not previously added the IBM Enterprise CPP Access Builder Examples feature to the Workbench, add it using File - Quick Start. Generate the C++ access beans and wrapper files 1. Select the com.ibm.ivj.examples.cpp package and click mouse button 2. 2. From the pop-up menu, select Tools - C++ Access - Create Access Beans. The C++ Header Files page of the C++ Access Builder SmartGuide opens. 3. Beside the Add C++ header files box, click Add to open the Load files dialog box. 4. Browse to the following directory (where path is the install path of VisualAge for Java):

path\Eab\samples\com\ibm\ivj\examples\cpp 5. Select the stack.hpp file and click Open. The C++ header file is added to the box. 6. Click Next. The C++ Code Generation page opens. 7. In the Library name field, type StStack. The name StStack will be given to the generated makefile and the shared library. 8. Click Next. The C++ Compiler page opens. 9. From the Select desired compiler pull-down menu, select the C++ compiler you want to use to preprocess the definition file. 10. In the Preprocessor command field, enter the commands required by your C++ compiler. A default command for the selected compiler appears in this field. You can accept the default or modify the command. 11. Click Next. The C++ Implementation Files page opens. 12. Beside the Add libraries box, click Add... to open the Load files dialog box. 13. Browse to the following directory (where path is the install path of VisualAge for Java):

path\Eab\samples\com\ibm\ivj\examples\cpp 14. Select the stack.lib file and click Open. This is the existing library the Java application will access. 15. Click Finish. The C++ Access Builder generates access beans and wrapper files into the com.ibm.ivj.examples.cpp package. Create the shared library From a command prompt, run nmake (or your C++ compiler’s make program) to process the shared library that will be accessed by the Java client’s access bean.

Chapter 9. Tutorial 47 Create the client class 1. Select the com.ibm.ivj.examples.cpp package. 2. Click mouse button 2, and from the pop-up menu, select Add -Application. The Create Application SmartGuide opens. 3. In the Package field, ensure the package name com.ibm.ivj.examples.cpp appears. 4. In the Class name field, type StStackWindow1. 5. Select the Create AWT based application radio button. 6. Click Finish. Add the StStack bean to the Visual Composition Editor 1. Maximize the Visual Compositon Editor. 2. On the Beans Palette, click the Choose Bean button. The Choose Bean dialog box opens. 3. Beside the Class name field, click Browse. The Choose a valid class dialog box opens. 4. In the Pattern field, type StStack, then in the Package Names list box, ensure that StStack is selected from the com.ibm.ivj.examples.cpp package. 5. Click OK to close the Choose a Valid Class dialog box. 6. In the Choose Bean dialog box, click OK. The cursor becomes a crosshair. 7. To the right of the frame window, click mouse button 1 to place the StStack bean on the free-form surface. It appears as a nonvisual bean named StStack1. Create the client program GUI To create the push buttons: 1. From the Beans palette, select the Button bean. The cursor becomes a crosshair. 2. Near the top of the frame window, click mouse button 1 to drop the button on the client program interface. 3. Repeat the previous two steps to create two more buttons, but drop one in the middle of the frame window and the other near the bottom of the frame window. 4. On the top button, click mouse button 2, and select Properties from the pop-up menu. A Property sheet opens. 5. From the left column, select Label and, in the right column, type Push. 6. Close the Property Sheet. The button is now labeled Push. 7. Repeat the previous three steps to label the middle button Pop and the bottom button Depth. To create the entry fields: 1. From the Beans palette, select the TextField bean. The cursor becomes a crosshair. 2. Above the Push button, in the frame window, click mouse button 1 to drop the entry field on the client program interface. 3. Create two more text fields, and place one above the Pop button and the other above the Depth button. 4. Resize the text fields to an appropriate length for text entry. Connect the client program GUI To connect the client program Push button:

48 C++ Access Builder 1. On the Push button, click mouse button 2 and select Connect - ActionPerformed from the pop-up menu. 2. Position the cursor with its pending connection on the StStack1 bean. 3. Click mouse button 1, and select Connectable Features from the pop-up menu. An End connection to dialog box opens. 4. From the Method list, select the push() method and click OK to establish the connection. 5. On the new connection, click mouse button 2. 6. From the pop-up menu, select Connect - arg1. 7. Position the pending connection on the Push text field and click mouse button 1. 8. From the pop-up menu, select text. To connect the Pop button: 1. On the Pop button, click mouse button 2. 2. From the pop-up menu, select Connect - ActionPerformed. 3. Position the pending connection on the StStack1 bean. 4. Click mouse button 1 and, from the pop-up menu, select Connectable Features. An End connection to dialog box opens. 5. From the Method list, select the pop() method and click OK to establish the connection. 6. On the new connection, click mouse button 2 and, from the pop-up menu, select Connect - normalResult. 7. Position the pending connection on the Pop text field. 8. Click mouse button 1 and, from the pop-up menu, select text. To connect the Depth button: 1. On the Depth button, click mouse button 2 and, from the pop-up menu, select Connect - ActionPerformed. 2. On the StStack1 bean, click mouse button 1 and, from the pop-up menu, select Connectable Features. An End connection to dialog box opens. 3. From the Method list, select the numberOfElements() method and click OK to establish the connection. 4. On the new connection between the Depth button and the StStack1 bean, click mouse button 2 and, from the pop-up menu, select Connect - normalResult. 5. Position the pending connection on the Depth text field. 6. Click mouse button 1 and, from the pop-up menu, select text. 7. From the Bean menu, select Save Bean. This compiles the client code. 8. Close the Visual Composition Editor. Run your sample program in the IDE 1. In the com.ibm.ivj.examples.cpp package, select the StStackWindow1 class. 2. Select Run - Check Class Path. The Properties for StStackWindow dialog opens. 3. On the Class Path tab, beside the Project Path field, click Edit. The Class Path dialog opens. 4. Ensure that the IBM Enterprise CPP Access Builder Library project is selected and click OK. 5. Click OK.

Chapter 9. Tutorial 49 6. From the Selected menu, select Run - Run main. The client window opens. 7. In the top field, type Apples and click Push. This adds an element to the stack. 8. In the top field, type Oranges and click Push. This adds another element to the stack. 9. Click Depth. The field above the Depth button shows that there are two elements on the stack. 10. Click Pop. The field above the Pop button indicates that the element Oranges has been popped off the stack. 11. Click Depth. The field above the Depth button now shows that there is one element on the stack. 12. Close the client window.

Run the sample program from the command line

Start the sample 1. From the command line, change to the following directory (where path is the install path of VisualAge for Java):

path\Eab\samples\com\ibm\ivj\examples\cpp 2. Issue the following command:

set CLASSPATH=path\Eab\samples;%CLASSPATH% 3. Issue the following command:

set PATH=path\Eab\samples\com\ibm\ivj\examples\cpp;%PATH% Run the sample as an application from the command line Issue the following command to run the client program as an application:

java Demo

In the command window, the client program displays the items pushed and popped and displays the number of elements on the stack.

50 C++ Access Builder Appendix. Reference Information

Makefile targets These targets assume the use of the default IBM C++ compiler.

The parameters are all optional. Only one parameter can be specified at a time. If no parameter is specified, the all parameter is specified by default. The command parameters are described in the table below:

Parameter Description all Generates all source code and builds the library containing the C++ wrappers and the C++ implementation code. clean Removes all files generated as a result of running make or nmake. class-files Generates and compiles the Java representative class files. wrapper-obj-files Generates and compiles the C++ wrapper files. imp-obj-files Compiles the implementation files of the C++ classes to be interfaced. obj-files Causes all object files to be generated from their respective sources.

C++ Access Builder: overview C++ Access Builder limitations Classes generated by the C++ Access Builder

Creating a shared library Generating C++ access beans and wrapper files

© Copyright IBM Corp. 1997, 2000 51 52 C++ Access Builder Notices

Note to U.S. Government Users Restricted Rights — Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

This information was developed for products and services offered in the U.S.A. IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user’s responsibility to evaluate and verify the operation of any non-IBM product, program, or service.

IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to:

IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 U.S.A.

For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property Department in your country or send inquiries, in writing, to:

IBM World Trade Asia Corporation Licensing 2-31 Roppongi 3-chome, Minato-ku Tokyo 106, Japan

The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you.

This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice.

Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web

© Copyright IBM Corp. 1997, 2000 53 sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk.

IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you.

Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact:

Lab Director IBM Canada Ltd. 1150 Eglinton Avenue East Toronto, Ontario M3C 1H7 Canada

Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee.

The licensed program described in this document and all licensed material available for it are provided by IBM under terms of the IBM Customer Agreement, IBM International Program License Agreement or any equivalent agreement between us.

Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products.

This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples may include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental.

COPYRIGHT LICENSE:

This information contains sample application programs in source language, which illustrates programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. You may copy, modify, and distribute these sample programs in any form without payment to IBM for the purposes of developing, using, marketing, or distributing application programs conforming to IBM’s application programming interfaces.

Each copy or any portion of these sample programs or any derivative work, must include a copyright notice as follows:

54 C++ Access Builder © (your company name) (year). Portions of this code are derived from IBM Corp. Sample Programs. © Copyright IBM Corp. 1997, 2000. All rights reserved.

Notices 55 56 C++ Access Builder Programming interface information

Programming interface information is intended to help you create application software using this program.

General-use programming interfaces allow the customer to write application software that obtain the services of this program’s tools.

However, this information may also contain diagnosis, modification, and tuning information. Diagnosis, modification and tuning information is provided to help you debug your application software.

Warning: Do not use this diagnosis, modification, and tuning information as a programming interface because it is subject to change.

© Copyright IBM Corp. 1997, 2000 57 58 C++ Access Builder Trademarks and service marks

The following terms are trademarks of International Business Machines Corporation in the United States, or other countries, or both: v AIX v AS/400 v DB2 v CICS v CICS/ESA v IBM v IMS v Language Environment v MQSeries v Network Station v OS/2 v OS/390 v OS/400 v RS/6000 v S/390 v VisualAge v VTAM v WebSphere Lotus, Lotus Notes and Domino are trademarks or registered trademarks of Lotus Development Corporation in the United States, or other countries, or both.

Tivoli Enterprise Console and Tivoli Module Designer are trademarks of Tivoli Systems Inc. in the United States, or other countries, or both.

Encina and DCE Encina Lightweight Client are trademarks of Transarc Corporation in the United States, or other countries, or both.

Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.

ActiveX, Microsoft, SourceSafe, Visual C++, Visual SourceSafe, Windows, Windows NT, Win32, Win32s and the Windows logo are trademarks or registered trademarks of Microsoft Corporation in the United States, or other countries, or both.

UNIX is a registered trademark in the United States and other countries licensed exclusively through X/Open Company Limited.

Intel and Pentium are trademarks of Intel Corporation in the United States, or other countries, or both.

Other company, product, and service names, which may be denoted by a double asterisk(**), may be trademarks or service marks of others.

© Copyright IBM Corp. 1997, 2000 59