Example 5-7. Account IDL file
interface Account { void deposit (in unsigned long amount); void withdraw (in unsigned long amount); readonly attribute long balance; };
if (!acc_client)...) before invoking calls to the server.
Example 5-8. Account Client Source
/*------- Account client (account-client.c)-----------------------------------------*/ #include <stdio.h> #include <orb/orbit.h> #include "account.h" int main (int argc, char *argv[]) { Account acc_client; /* The client-side Account object */ CORBA_long val; /* client stores the balance here */ PortableServer_POA poa; CORBA_ORB orb=NULL; /* This is our ORB */ char *ior; /* an IOR is one way a client can locate a server */ CORBA_Environment ev; /* CORBA exception information */ CORBA_exception_init(&ev); /* Initialize the orb. The initialization routine checks the command * line parameters for directives that affect the orb */ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); /* Bind our client Account to the account on the server using the * IOR to look it up (the ior was gotten above in the server code) */ acc_client = CORBA_ORB_string_to_object(orb, argv[1], &ev); if (!acc_client) { printf("Cannot bind to %s\n (pass the IOR as arg 1)\n", argv[1]); exit(1); } val = Account__get_balance(acc_client, &ev); printf ("Initial balance is %d.\n",val); printf("Make a deposit, how :"); scanf("%d",&val); Account_deposit(acc_client, (CORBA_unsigned_long) val, &ev); val = Account__get_balance(acc_client, &ev); printf ("Balance is %d.\n",val); Account_withdraw(acc_client, (CORBA_unsigned_long) 5, &ev); val = Account__get_balance(acc_client, &ev); printf ("Balance is %d.\n",val); /* We're done now. Do some cleanup */ CORBA_Object_release(acc_client, &ev); exit (0); }
Now, let us edit account-skelimpl.c. We search for the the balance attribute that was declared in the IDL file. At the beginning of the file, we can spot the way it has been translated into C by the idl compiler:
Example 5-9. Skeleton Implementation for the account server
/*** App-specific servant structures ***/ typedef struct { POA_Account servant; PortableServer_POA poa; CORBA_long attr_balance; } impl_POA_Account;So, the server methods (withdraw and deposit) will have to manage the balance of the account through the servant->attr_balance(the servant variable is passed as parameter to each method).
Now, let us get to the end of the file and find the methods stubs. We find the impl_Account_* functions, to which we add the implementation code. This could be:
static void impl_Account_deposit(impl_POA_Account *servant, CORBA_unsigned_long amount, CORBA_Environment *ev) { printf("server calls deposit method...\n"); servant->attr_balance += amount; } static void impl_Account_withdraw(impl_POA_Account *servant, CORBA_unsigned_long amount, CORBA_Environment *ev) { printf("server calls withdraw method...\n"); servant->attr_balance -= amount; } static CORBA_long impl_Account__get_balance(impl_POA_Account *servant, CORBA_Environment *ev) { CORBA_long retval; retval= servant->attr_balance; return retval; }Lastly, we have to write a rather generic code to set up the server. We call it account-server.c. It is roughly the same code as in the calculator and echo examples. The code just initializes the ORB and publish an IOR for the server object.
Example 5-10. Account Server C Source
/*------- Account server (account-server.c)-----------------------------------------*/ #include "account-skelimpl.c" #include <stdio.h> int main (int argc, char *argv[]) { CORBA_ORB orb; CORBA_Environment* ev; PortableServer_ObjectId* oid; Account account; PortableServer_POA root_poa; PortableServer_POAManager pm; CORBA_char* ior; ev = g_new0(CORBA_Environment,1); CORBA_exception_init(ev); /* Initialize the orb. The initialization routine checks the command * line parameters for directives that affect the orb */ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev); root_poa = (PortableServer_POA) CORBA_ORB_resolve_initial_references(orb, "RootPOA", ev); /* ask for instanciation of one object account */ account = impl_Account__create(root_poa, ev); /* Here we get the IOR for the acc object. Our "client" will use * the IOR to find the server to connect to */ ior = CORBA_ORB_object_to_string(orb, account, ev); /* print out the IOR, just so you can see what it looks like */ printf ("%s\n", ior); pm = PortableServer_POA__get_the_POAManager(root_poa, ev); PortableServer_POAManager_activate(pm,ev); CORBA_ORB_run(orb, ev); return (0); }
Example 5-11. Makefile for the Account example
PROJECT = account CC = gcc ORBIT_IDL = /usr/bin/orbit-idl ORBIT_CFLAGS = -I/usr/lib/glib/include -I/usr/include ORBIT_LIBS = -L/usr/lib -lORBit -lIIOP -lORBitutil -lglib -lm CFLAGS = $(ORBIT_CFLAGS) LFLAGS = $(ORBIT_LIBS) all : idltargets $(PROJECT)-client $(PROJECT)-server $(PROJECT)-client : $(PROJECT)-client.o $(PROJECT)-common.o $(PROJECT)-stubs.o $(CC) -o $(PROJECT)-client $(PROJECT)-client.o $(PROJECT)-stubs.o $(PROJECT)-common.o -lIIOP -lORBit -lORBitutil $(LFLAGS) $(PROJECT)-server : $(PROJECT)-server.o $(PROJECT)-skels.o $(PROJECT)-common.o $(CC) -o $(PROJECT)-server $(PROJECT)-server.o $(PROJECT)-skels.o $(PROJECT)-common.o -lIIOP -lORBit -lORBitutil $(LFLAGS) clean : rm *.[oa] $(PROJECT)-client $(PROJECT)-server real-clean : clean rm -f $(PROJECT)-stubs.[oc] $(PROJECT)-skels.[oc] $(PROJECT).h $(PROJECT)-common.[oc] idltargets : $(PROJECT).idl $(ORBIT_IDL) $(PROJECT).idl # individual rules $(PROJECT)-stubs.c : $(PROJECT).idl $(ORBIT_IDL) $(PROJECT).idl $(PROJECT)-common.c : $(PROJECT).idl $(ORBIT_IDL) $(PROJECT).idl $(PROJECT)-skels.c : $(PROJECT).idl $(ORBIT_IDL) $(PROJECT).idl $(PROJECT)-client.c : $(PROJECT).h $(PROJECT)-server.c : $(PROJECT).h $(PROJECT).h : $(PROJECT).idl $(ORBIT_IDL) $(PROJECT).idl