C codebase

This section describes how to design, develop, deploy and run a "HelloWorld" application in the C codebase, under the following headings:

Designing the C "HelloWorld" application

This application aims to create and use a single queue manager with a local queue. It involves putting a message to the local queue and then removing it.

You can create queue managers for use by one program. Once this program has completed, you can run a second program that reinstates the previous queue manager configuration.

Typically, configuring new entities is a separate process from their actual use. Once configured, administering these entities also requires a different process than using them. This section concentrates on usage rather than administration. The WebSphere MQ Everyplace Configuration Guide contains information on configuring and administering resources.

Assuming that the queue manager entity has already been configured, the HelloWorld application has the following flow for both the C and Java codebases:

  1. Start the queue manager
    This starts the queue manager based on information already created
  2. Create a message
    Creates a structure that you can use to send a message from one queue manager to another
  3. Put to a local queue
    Puts the message on the local queue
  4. Get from a local queue
    Retrieves the message from the local queue and checks that the message is valid
  5. Shutdown
    Clears and stops the queue manager
Note:
The C codebase does not have an equivalent of the Java Garbage Collection function. Therefore, clearing the queue manager features more strongly in C.

Developing the C "HelloWorld" application

This section covers the high level coding required for the "HelloWorld" application.

C Development

The following code is in the example HelloWorld_Runtime.c in its complete state. The example contains code to handle the specifics of running a program on a PocketPC, which mainly involves writing to a file to cope with the lack of command line options. Use the display function to write to a file, as shown in the examples contained in the following sections.

Preparation

You need to include just one header file to access the APIs.

Note:
You must include the NATIVE definition to indicate that this is not the CBindings. You must also define the MQE_PLATFORM upon which you intend to run the application.
	#define 	NATIVE
	#define	MQE_PLATFORM = PLATFORM_WINCE
	#include<published/MQe_API.h>

All of the code, including variable declarations, is inside the main method. You require structures for error checking. The MQeExceptBlock structure is passed into all functions to get the error information back. In addition, all functions return a code indicating success or failure, which is cached in a local variable:

		/* ... Local return flag */   
		 MQERETURN            rc;    
		 MQeExceptBlock       exceptBlock; 

You must create a number of strings, for example for the queue manager name:

		MQeStringHndl     hLocalQMName;  
		
			 		...    	    
		
		 if ( MQERETURN_OK == rc ) {
				rc = mqeString_newUtf8(&exceptBlock,
												&hLocalQMName,
												"LocalQM");
		}	

The first API call made is session initialize:

		/* ... Initalize the session */    
		rc = mqeSession_initialize(&exceptBlock);
  
Stage 1: Start the queue manager

This process involves two steps:

  1. Create the queue manager item.
  2. Start the queue manager.

Creating the queue manager requires two sets of parameters, one set for the queue manager and one for the registry. Both sets of parameters are initialized. The queue store and the registry require directories.

Note:
All calls require a pointer to ExceptBlock and a pointer to the queue manager handle.
 		if (MQERETURN_OK == rc) {  
		
		MQeQueueManagerParms qmParams  = QMGR_INIT_VAL;     
		MQeRegistryParms     regParams = REGISTRY_INIT_VAL;      
		qmParams.hQueueStore           = hQueueStore;                    
		qmParams.opFlags               = QMGR_Q_STORE_OP;         
		
		/* ... create the registry parameters - 
				minimum that are required */    
		regParams.hBaseLocationName     =  hRegistryDir;    
		display("Loading Queue Manager from registry \n");    
		rc = mqeQueueManager_new(	&exceptBlock, 
                      			&hQueueManager,   
                          	 hLocalQMName,     
                         		&qmParams,    
                         		&regParams); 
}	

You can now start the queue manager and carry out messaging operations:

		 /* Start the queue manager  */     
		
		if ( MQERETURN_OK == rc ) {        
			 display("Starting the Queue Manager\n");        
			 rc = mqeQueueManager_start(hQueueManager,
												&exceptBlock);    
		}
Stage 2: Create a message

To create a message, firstly create a new fields object. The following example adds a single field. Note that the field label strings are passed in:

	MQeFieldsHndl hMsg;  
	
	display("Creating a new message\n"); 
	rc = mqeFields_new(&exceptBlock,&hMsg); 
	if ( MQERETURN_OK == rc ) {    
		rc = mqeFields_putInt32(hMsg,&exceptBlk,
											hFieldLabel,42); 
	} 
Stage 3: Put to a local queue

Once you have created the message, you can put it to a local queue using the putMessage function. Note that the queue and queue manager names are passed in. NULL and 0 are passed in for the security and assured delivery parameters, as they are not required in this example. Once the message has been put, you can free the MQeFields object:

		if ( MQERETURN_OK == rc ) {  
   	  	 display("Putting a message \n");   
     			rc = mqeQueueManager_putMessage(hQueueManager,
                                     		&exceptBlock,  
                                     		 hLocalQMName,   
                                     		 hLocalQueueName,     
                                    		 hMsg,   
                                     		 NULL,    
                                     		 0);   
                                                                  
    	 	(void) mqeFields_free(hMsg,NULL);   
    	}                       
Stage 4: Get from a local queue

Once the message has been put to a queue, you can retrieve and check it. Similar options are passed to the getMessage function. The difference is that a pointer to a fields handle is passed in. A new Fields object is created, removing the message from the queue:

		MQeFieldsHndl hReturnedMessage; 
		display("Getting the message back \n");  
		
		rc = mqeQueueManager_getMessage(hQueueManager,					
                               			&exceptBlock,					
										  			&hReturnedMessage,					
													 hLocalQMName,					
													 hLocalQueueName,					
                                		 NULL, 				
                                		 NULL,					
                                	 	 0);     
   }                

Once the message has been obtained, you can check it for the value that was entered. Obtain this by using the getInt32 function. If the result is valid, you can print it out:

		if (MQERETURN_OK == rc) {                                     
			MQEINT32 answer;                                           
	 		rc = mqeFields_getInt32(hReturnedMessage,							
                          		&exceptBlock,							
		 									&answer,  								
                           		 hFieldLabel);									 
                                                                    
		if (MQERETURN_OK == rc) {                                     
			display("Answer is %d\n",answer);                          
		} 
		else {                                                        
	 		display(  "\n\n        %s  (0x%X)     %s (0x%X)\n", 
						mapReturnCodeName(EC(&exceptBlock))  , 
						EC(&exceptBlock), 
						mapReasonCodeName(ERC(&exceptBlock)), 
						ERC(&exceptBlock)  );   
			}
	
		}
Stage 5: Shutdown

Following the removal of the message from the queue, you can stop and free the queue manager. You can also free the strings that were created. Finally, terminate the session:

		(void)mqeQueueManager_stop(hQueueManager,&exceptBlock);     
		(void)mqeQueueManager_free(hQueueManager,&exceptBlock);     
		
		/* Lets do some clean up */     
		(void)mqeString_free(hFieldLabel,&exceptBlock);     
		(void)mqeString_free(hLocalQMName,&exceptBlock);     
		(void)mqeString_free(hLocalQueueName,&exceptBlock);     
		(void)mqeString_free(hQueueStore,&exceptBlock);     
		(void)mqeString_free(hRegistryDir,&exceptBlock);    
		
		
		(void)mqeSession_terminate(&exceptBlock); 

C Compilation

To simplify the process of compiling, the examples directory includes a makefile. This is the makefile exported from eMbedded Visual C (EVC). A batchfile runs this makefile. This batch file will setup the paths to the EVC directories, along with the paths to the WebSphere MQ Everyplace installation. You may need to edit the batch file, depending on how you want to install WebSphere MQ Everyplace.

Running the batch file will compile the example. By default, the batch file compiles for Debug PocketPC 2000 (either Emulator or ARM processor).

Deploying the C "HelloWorld" application

In order to deploy the "HelloWorld" application, you need to create a queue manager. There are various ways to do this, which are covered in the WebSphere MQ Everyplace Configuration Guide. In this case, the HelloWorld_Admin program is used. Run this as described below.

C deployment

The next chapter, Running applications, covers C deployment in detail. The basics, applicable to both the emulator and an actual device, are as follows:

  1. Copy across all the DLLs to the root of the device. Take these from either the arm or x86 emulator directories.
  2. Build the example code using the supplied makefile.
    Note:
    You need to compile the HelloWorld_Admin.c and HelloWorld_Runtime.c files.
  3. Copy across these binaries to the device or emulator that is running PocketPC or Emulator.

Running the C "HelloWorld" application

This section describes how to run the "HelloWorld" application in Java and C.

PocketPC or emulator

This example involves two steps:

  1. Create the queue manager. To do this, run the HelloWorld_Admin program.Running this creates the persistent disk representation of the QueueManager.
  2. Run the HelloWorld_Runtime program. This starts a QueueManager based upon the established registry. To check the program has worked correctly, look at the log file that has been generated. By default, this is in the root of the device.