Chapter 3 Creating C++ Components and Clients
To create and run the sample application:
Before running the tutorial, verify these environment settings:
| Platform | Variable name |
|---|---|
| Solaris |
LD_LIBRARY_PATH |
| HP-UX |
SHLIB_PATH |
| AIX |
LIBPATH |
| Linux |
LD_LIBRARY_PATH |
Configuring the Windows environment
set JAGUAR=eas-home set PATH=%JAGUAR%\dll;%PATH%
Configuring the UNIX environment for C shell
setenv JAGUAR eas-home setenv LIB_PATH $JAGUAR/lib:$LIB_PATH
setenv JAGUAR eas-home setenv LD_LIBRARY_PATH \ $JAGUAR/lib_sol4x:$LD_LIBRARY_PATH
Configuring the UNIX environment for Bourne shell
JAGUAR=eas-home export JAGUAR LIB_PATH=$JAGUAR/lib:$LIB_PATH export LIB_PATH
JAGUAR=eas-home export JAGUAR LD_LIBRARY_PATH=$JAGUAR/lib_sol4x:$LD_LIBRARY_PATH export LD_LIBRARY_PATH
Starting the server
Starting EAServer Manager
This section shows you how to use EAServer Manager to create the package, component, and method for the sample application.
For complete information on configuring packages, components, and methods, see Chapter 5, "Defining Component Interfaces," in the EAServer Programmer's Guide.
In EAServer, a package is a unit of deployment for a group of components that perform related tasks. All components created in the EAServer tutorials are installed in the Tutorial package.
Before a component can be instantiated by clients, it must be installed in a package, and that package must be installed in the server. The steps below create the package and component within the predefined "Jaguar" server to satisfy these requirements.
Creating the Tutorial package if it does not exist
Tutorial
.
You will define a new C++ component, CPPArithmetic.
Defining the component
CPPArithmetic
.
| Field | Value |
|---|---|
| Description | Tutorial C++ component |
| Codeset | Server's Codeset (default) |
| Component Type | C++ |
| DLL Name | libCPPArithmetic
(no
extension)
|
| C++ Class | CPPArithmeticImpl
|
| C++ Executable | (blank) |
| Use Platform Independent Naming | Unchecked |
The component interface will have one method, multiply.
Defining the component interface
m1
.
in
.
double
.
m2
with
a Type of double.
Once you have created the package, component, and methods, you can generate the stub and skeleton files for the component. The client executable uses the stubs to invoke the server-side component methods. The server uses the skeleton to invoke your component implementation class.
Generating the stubs and skeletons
EAServer Manager has generated C++ implementation templates for the component methods. Here we will fill in the implementation template, then build a shared library or DLL file. Finally, we will verify that the shared library or DLL is in the EAServer cpplib subdirectory, where EAServer expects to find C and C++ component library files.
Writing the server-side code
CORBA::Double CPPArithmeticImpl::multiply
(CORBA::Double m1,
CORBA::Double m2)
{
CORBA::Double result;
result = m1 * m2;
return result;
}
Building the component on Windows
ODBCHOME=d:\msdev
ODBCHOME="D:\engapps\devStudio\VC98"
You should see a new file called libCPPArithmetic.dll. Verify that the makefile has copied this file to the EAServer cpplib subdirectory. If nmake fails, verify that you have renamed the .cpp and .hpp implementation files with the expected file names, and that you have applied the correct edits to CPPArithmeticImpl.cpp and Makefile.
Building the component on UNIX platforms
-L$JAGUAR/lib
to -L$JAGUAR/lib_sol4x
.
You must use the compiler version that is compatible with your server.
The default server binary requires libraries compatible with the
6.x compiler, but you can override this setting
when starting the server. For more information, see "Starting the
server" in the EAServer System Administration
Guide.
You should see a new file called libCPPArithmetic.ext, where ext is the appropriate shared library extension for your platform. Verify that the makefile has copied this file to the EAServer cpplib subdirectory.
If make fails, verify the following:
uname -s
on
your system. If necessary, edit this file to match your system configuration.
Create the source file for the sample C++ client, arith.cpp. You can find a copy of arith.cpp in the html/docs/tutorial/cpp subdirectory of your EAServer installation. Here is the source for arith.cpp:
/*
** arith.cpp -- Example C++ client for the EAServer C++
** tutorial.
**
** This program connects to EAServer,
** creates an instance of the Tutorial/CPPArithmetic
** component, and invokes the multiply method.
**
** Usage:
** arith iiop://<host>:<port>
**
** Where:
**
** <host> is the host name or IP address of the server machine.
**
** <iiop-port> is the server's IIOP port (9000 in the
** default configuration).
**
*/
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <Jaguar.hpp>
#include <SessionManager.hpp>
#include <Tutorial.hpp> // Stubs for interfaces in Tutorial IDL
// module.
int main(int argc, char** argv)
{
const char *usage =
"Usage:\n\tarith iiop://<host>:<iiop-port>\n";
const char *tutorial_help =
"Check Jaguar Manager and verify that the"
"Tutorial/CPPArithmetic component exists "
"and that it implements the "
"Tutorial::CPPArithmetic IDL interface.";
const char *component_name = "Tutorial/CPPArithmetic";
try {
if (argc < 2)
{
cout << usage;
return -1;
}
char* manager_url = argv[1];
cout << "**** Creating session\n";
// Initialize the ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, 0);
// Create a SessionManager::Manager instance
CORBA::Object_var obj =
orb->string_to_object(manager_url);
SessionManager::Manager_var manager =
SessionManager::Manager::_narrow(obj);
if (CORBA::is_nil(manager))
{
cout << "Error: Null SessionManager::Manager instance. Exiting. "
<< usage ;
return -1;
}
// Create an authenticated session for user Guest
// using password GuestPassword
SessionManager::Session_var session =
manager->createSession("Guest", "GuestPassword");
if (CORBA::is_nil(session))
{
cout << "Error: Null session. Exiting. " << usage;
return -1;
}
// Obtain a factory for component instances by
// resolving the component name
cout << "**** Creating component instance for "
<< component_name << "\n" ;
obj = session->lookup(component_name);
SessionManager::Factory_var arithFactory =
SessionManager::Factory::_narrow(obj);
if (CORBA::is_nil(arithFactory))
{
cout << "ERROR: Null component factory for component "
<< component_name
<< tutorial_help ;
return -1;
}
// Use the factory to create an instance.
Tutorial::CPPArithmetic_var arith =
Tutorial::CPPArithmetic::_narrow(arithFactory->create());
// Verify that we really have an instance.
if (CORBA::is_nil(arith)) {
cout << "ERROR: Null component instance. "
<< tutorial_help ;
return -1;
}
// Call the multiply method.
cout << "**** Multiplying ...\n\n";
CORBA::Double m1 = (CORBA::Double)3.1;
CORBA::Double m2 = (CORBA::Double)2.5;
CORBA::Double result = arith->multiply(m1, m2);
cout << (double)m1 << " * " << (double)m2
<< " = " << (double)result
<< "\n\n";
}
// Explicitly catch exceptions that can occur due to user error,
// and print a generic error message for any other CORBA system
// exception.
// Requested object (component) does not exist.
catch ( CORBA::OBJECT_NOT_EXIST cone )
{
cout << "Error: CORBA OBJECT_NOT_EXIST exception. Check the "
<< "server log file for more information. Also verify "
<< "that the " << component_name
<< " component has been created properly in "
<< "Jaguar Manager. " << tutorial_help ;
}
// Authentication or authorization failure.
catch ( CORBA::NO_PERMISSION npe )
{
cout << "Error: CORBA:: NO_PERMISSION exception. Check whether "
<< "login authentication is enabled for your server and "
<< "whether the component has restricted access. If so "
<< "edit the source file to use a valid user name and "
<< "password.\n";
}
// Invalid object reference.
catch ( CORBA::INV_OBJREF cio )
{
cout << "Error: CORBA INV_OBJREF exception.";
}
// Communication failure. Server could be down or URL's port value
// could be wrong.
catch ( CORBA::COMM_FAILURE ccf )
{
cout << "Error: CORBA COMM_FAILURE exception. Check that the "
<< "specified host and IIOP port number are "
<< "correct and that the server is running. "
<< usage;
}
// Anything else.
catch ( CORBA::OBJ_ADAPTER )
{
cout << "Error: CORBA::OBJ_ADAPTER \n";
}
catch ( CORBA::SystemException cse )
{
cout << "Error: CORBA System Exception. Check that the server "
<< "hostname and IIOP port are specified correctly, and "
<< "check the server's error log for more information.\n"
<< usage;
}
return 0;
}
Compiling the client on Windows
SETLOCAL call %JAGUAR%\bin\setenv.bat set INCLUDE=.;%JAGUAR%\include;%INCLUDE%; set INCLUDE=%INCLUDE%;%JAGUAR_JDK13%\include; set INCLUDE=%INCLUDE%;%JAGUAR_JDK13%\include\win32 set LIB=%JAGUAR%\lib;%LIB% cl /W3 /nologo /DWIN32 /Gd /GX -c arith.cpp set SYSLIBS=kernel32.lib advapi32.lib link /MAP /out:arith.exe arith.obj libjcc.lib libjutils.lib %SYSLIBS% ENDLOCAL
Compiling the client on UNIX
chmod 777 compile.sh
| Platform | Shell script |
|---|---|
| Solaris | This shell script works with the Solaris
CC compiler, version 6.x:
#!/bin/sh . $JAGUAR/bin/setenv.sh CC -DJAG_NO_NAMESPACE -z muldefs -I. -I$JAGUAR/include \ -I$JAGUAR_JDK13/include -I$JAGUAR_JDK13/include/solaris \ -L$JAGUAR/lib -ljcc -ljtml_r -ljtli_r -lunic -lnsl \ -ldl -lthread -lm -ljutils -o arith arith.cpp If you use the version 4.x compiler, change -L$JAGUAR/lib
to -L$JAGUAR/lib_sol4x
.
|
| HP-UX | This shell script uses the HP-UX ANSI
C++ (aCC) compiler:
#!/bin/sh . $JAGUAR/bin/setenv.sh aCC -c +DA1.1 +DS2.0 +u4 -DNATIVE -D_HPUX -D_POSIX_C_SOURCE=199506L \ -D_HPUX_SOURCE -I $(JAGUAR_JDK13)/include -I $(JAGUAR_JDK13)/include/hp-ux \ -I $(JAGUAR_JDK12)/include -I $(JAGUAR_JDK12)/include/hp-ux -I. \ -I$JAGUAR/include -L$JAGUAR/lib -lpthread -ljcc -lnsl -ljtml_r \ -ljinsck_r -lunic -ljutils -o arith arith.cpp |
| AIX | This shell script uses the IBM native
compiler:
#!/bin/sh . $JAGUAR/bin/setenv.sh xlC_r -g -c -DDEBUG -DJAG_NO_NAMESPACE -DAIX -D_AIX -qcpluscmt -qnoro \ -qmaxmem=-1 -qarch=com -qtbtable=full -I $(JAGUAR_JDK13)/include \ -I $(JAGUAR_JDK12)/include -I. -I$JAGUAR/include \ -brtl -L$JAGUAR/lib -ljcc.so -lunic -ljtml_r.so -ljinsck_r.so \ -lpthread -lnsl -ljutils -o arith arith.cpp |
| Linux | This shell script uses the g++ compiler:
#!/bin/sh . $JAGUAR/bin/setenv.sh g++ -c -D_GNU_SOURCE=1 -DLINUX -D_LINUX -D_REENTRANT -fPIC \ -fwritable-strings -pipe -g -DDEBUG -I $(JAGUAR_JDK13)/include \ -I $(JAGUAR_JDK13)/include/linux -I $(JAGUAR_JDK12)/include \ -I $(JAGUAR_JDK12)/include/linux -I. -I$JAGUAR/include \ -L$JAGUAR/lib -lpthread -ljcc -lnsl -ljtml_r -ljinsck_r \ -l unic -ljutils -o arith arith.cpp |
If you have not refreshed or restarted the server since creating the CPPArithmetic component, do so now before running the client program. Make sure your environment is configured as described in "Verify your environment".
Run the executable, specifying the server host name and IIOP port number on the command line as follows:
arith iiop://host:iiop-port
For example:
arith iiop://myhost:9000
If everything is working, arith prints the results from the invocation of the multiply method. If not, check the error text printed on the console where you ran the client, and check for error messages in the server log file.
| Copyright (C) 2004. Sybase Inc. All rights reserved. |
| |