ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » General IBM MQ Support » Coding LLZZ IMS header in C++

Post new topic  Reply to topic Goto page Previous  1, 2
 Coding LLZZ IMS header in C++ « View previous topic :: View next topic » 
Author Message
rekarm01
PostPosted: Wed Mar 11, 2020 2:09 pm    Post subject: Re: Coding LLZZ IMS header in C++ Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 1415

gpklos wrote:
So I couldn't get any of these options to compile, they all complained that I was trying assign something to *char that wasn't the same type.

I forgot the disclaimer: any posted code is untested. For further help, please post the exact error messages, along with the relevant code.

gpklos wrote:
I tried the static_cast and that also complained.

C++ has all kinds of cast operators to choose from; 'reinterpret_cast' may work better here:

Code:
msg.write( 2, reinterpret_cast<char *>(&imslen));     // Total message length.
msg.write( 2, reinterpret_cast<char *>(imsflags));    // IMS flags.

Or, when all else fails, try the plain old C-style cast operator:

Code:
msg.write( 2, (char *) &imslen);     // Total message length.
msg.write( 2, (char *) imsflags);    // IMS flags.
Back to top
View user's profile Send private message
gpklos
PostPosted: Fri Mar 13, 2020 10:33 am    Post subject: Re: Coding LLZZ IMS header in C++ Reply with quote

Centurion

Joined: 24 May 2002
Posts: 108

rekarm01 wrote:
gpklos wrote:
So I couldn't get any of these options to compile, they all complained that I was trying assign something to *char that wasn't the same type.

I forgot the disclaimer: any posted code is untested. For further help, please post the exact error messages, along with the relevant code.

gpklos wrote:
I tried the static_cast and that also complained.

C++ has all kinds of cast operators to choose from; 'reinterpret_cast' may work better here:

Code:
msg.write( 2, reinterpret_cast<char *>(&imslen));     // Total message length.
msg.write( 2, reinterpret_cast<char *>(imsflags));    // IMS flags.

Or, when all else fails, try the plain old C-style cast operator:

Code:
msg.write( 2, (char *) &imslen);     // Total message length.
msg.write( 2, (char *) imsflags);    // IMS flags.


I understand about the Disclaimer. I would never hold someone to their code on here. But on a good note it worked using the old C-style cast operator. I think the reinterpret_cast worked too but I didn't try that much.
I also got something working with modifying the imsbridge program that Morag found. I had to do some modifications to it, but it seems to work. It is a little different than what I was trying here with the msg.write. It uses msg.useEmptyBuffer to store the data to be written. Then you just use memmove to populate the buffer. So you just have to shove the LLZZ in the front using the memmove. I'm making it sound like it was so easy, but it really wasn't for me. If it wasn't for all the help you all have given me, I would never have gotten this to work.

Here is a code snippet of the IMS Bridge program that Morag found that works. Again some modifications were done on it.

char *localbuffer = new char[bufsize];
msg.useEmptyBuffer(localbuffer, bufsize);

int offset = 0;
short LL = 0;
short ZZ = 0;

char data[] = "TRANCODEDATATOTRANSACTION"; // This particular message has the IMS transaction in the first 8 bytes, followed by the Data passed to that transaction.

/*********************************************************/
/* The LL field contains the size of the message plus */
/* 2 bytes for the LL plus 2 bytes for the ZZ */
/* ZZ contains zeros. */
/* This section puts the LLZZ header in front of the */
/* regular data, which consists of the IMS transaction */
/* and the data. */
/*********************************************************/
LL = strlen(data) + 2 * sizeof(short);
cout << "The size of the data is " << LL << endl;

memmove(localbuffer + offset, &LL, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, &ZZ, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, data,LL);

msg.setMessageLength(LL);


if (!queue.put(msg)) ….


Hopefully this is the last of this, but again thank you all!!!

Gary
Back to top
View user's profile Send private message
tczielke
PostPosted: Fri Mar 13, 2020 2:55 pm    Post subject: Reply with quote

Guardian

Joined: 08 Jul 2010
Posts: 939
Location: Illinois, USA

Do you only plan on running this code on a server that uses the x86 processor? Just a note that if you run that code on most other CPUs, it would write out the first 4 bytes in the message as follows:

00 19 00 00
_________________
Working with MQ since 2010.
Back to top
View user's profile Send private message
rekarm01
PostPosted: Mon Mar 16, 2020 4:30 am    Post subject: Re: Coding LLZZ IMS header in C++ Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 1415

gpklos wrote:
But on a good note it worked using the old C-style cast operator. I think the reinterpret_cast worked too but I didn't try that much.

C++ tried to improve on some of the functionality it inherited from C, so there's some overlap between the two (such as cast vs. reinterpret_cast, char[] vs. string, and C functions vs. available C++ classes like ImqBinary or ImqString). A lot of developers end up using C++ to write mostly C programs, (because C seems easier), without realizing the need for additional logic, or error-checking.

gpklos wrote:
Code:
char *localbuffer = new char[bufsize];

If 'bufsize' is constant, then the 'new' operator is unnecessary; just declare 'localbuffer' as a char array. Otherwise, pair 'new' with 'delete []' whenever possible, to improve memory usage, and avoid leaks:

Code:
char localbuffer[bufsize];
// or
// char *localbuffer = new char[bufsize];
// ...
// delete [] localbuffer;

This is usually better than relying on whatever garbage collection, if any, that a C++ implementation may offer.

gpklos wrote:
Code:
short LL = 0;
short ZZ = 0;

On many platforms, a 'short' happens to be two bytes, but C++ does not guarantee this. That is one reason why C++ needs a 'sizeof' operator, and why IBM MQ defines its own platform independent types to increase program portability. Also, 'unsigned short' works better here, (though not as well as the MQUINT16 and MQBYTE[2] datatypes I recommended previously).

gpklos wrote:
Code:
LL = strlen(data) + 2 * sizeof(short);

strlen() counts bytes, not characters, and stops counting when it encounters a null byte, so it won't work as expected for double-byte or multi-byte character sets. Also, the code should make sure that 'LL' doesn't exceed 'bufsize' to avoid buffer overflow, (or exceed 2^16-1 to avoid integer overflow).

gpklos wrote:
Code:
memmove(localbuffer + offset, &LL, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, &ZZ, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, data, LL);

Ugh. That's definitely C, not C++. memcpy() may perform slightly better than memmove() here. The code works, (aside from the caveats mentioned above), but is a bit trickier and more error-prone than it might appear, compared to the three msg.write() calls in a previous example.

tczielke wrote:
Do you only plan on running this code on a server that uses the x86 processor? Just a note that if you run that code on most other CPUs, it would write out the first 4 bytes in the message as follows:

00 19 00 00

According to the documentation for MQFMT_IMS_VAR_STRING, MQ uses the Encoding field to interpret the first two bytes (LL), but not the next two bytes (ZZ).
Back to top
View user's profile Send private message
tczielke
PostPosted: Wed Mar 18, 2020 8:54 am    Post subject: Re: Coding LLZZ IMS header in C++ Reply with quote

Guardian

Joined: 08 Jul 2010
Posts: 939
Location: Illinois, USA

rekarm01 wrote:
tczielke wrote:
Do you only plan on running this code on a server that uses the x86 processor? Just a note that if you run that code on most other CPUs, it would write out the first 4 bytes in the message as follows:

00 19 00 00

According to the documentation for MQFMT_IMS_VAR_STRING, MQ uses the Encoding field to interpret the first two bytes (LL), but not the next two bytes (ZZ).


Ok, so similar to how the MQ C samples work where the md.Encoding field gets defaulted correctly based on how each cmqc.h file sets the #define MQENC_NATIVE value appropriately per system. Makes sense.
_________________
Working with MQ since 2010.
Back to top
View user's profile Send private message
gpklos
PostPosted: Thu Mar 19, 2020 10:43 am    Post subject: Re: Coding LLZZ IMS header in C++ Reply with quote

Centurion

Joined: 24 May 2002
Posts: 108

rekarm01 wrote:
gpklos wrote:
But on a good note it worked using the old C-style cast operator. I think the reinterpret_cast worked too but I didn't try that much.

C++ tried to improve on some of the functionality it inherited from C, so there's some overlap between the two (such as cast vs. reinterpret_cast, char[] vs. string, and C functions vs. available C++ classes like ImqBinary or ImqString). A lot of developers end up using C++ to write mostly C programs, (because C seems easier), without realizing the need for additional logic, or error-checking.

gpklos wrote:
Code:
char *localbuffer = new char[bufsize];

If 'bufsize' is constant, then the 'new' operator is unnecessary; just declare 'localbuffer' as a char array. Otherwise, pair 'new' with 'delete []' whenever possible, to improve memory usage, and avoid leaks:

Code:
char localbuffer[bufsize];
// or
// char *localbuffer = new char[bufsize];
// ...
// delete [] localbuffer;

This is usually better than relying on whatever garbage collection, if any, that a C++ implementation may offer.

gpklos wrote:
Code:
short LL = 0;
short ZZ = 0;

On many platforms, a 'short' happens to be two bytes, but C++ does not guarantee this. That is one reason why C++ needs a 'sizeof' operator, and why IBM MQ defines its own platform independent types to increase program portability. Also, 'unsigned short' works better here, (though not as well as the MQUINT16 and MQBYTE[2] datatypes I recommended previously).

gpklos wrote:
Code:
LL = strlen(data) + 2 * sizeof(short);

strlen() counts bytes, not characters, and stops counting when it encounters a null byte, so it won't work as expected for double-byte or multi-byte character sets. Also, the code should make sure that 'LL' doesn't exceed 'bufsize' to avoid buffer overflow, (or exceed 2^16-1 to avoid integer overflow).

gpklos wrote:
Code:
memmove(localbuffer + offset, &LL, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, &ZZ, sizeof(short));
offset += sizeof(short);
memmove(localbuffer + offset, data, LL);

Ugh. That's definitely C, not C++. memcpy() may perform slightly better than memmove() here. The code works, (aside from the caveats mentioned above), but is a bit trickier and more error-prone than it might appear, compared to the three msg.write() calls in a previous example.

tczielke wrote:
Do you only plan on running this code on a server that uses the x86 processor? Just a note that if you run that code on most other CPUs, it would write out the first 4 bytes in the message as follows:

00 19 00 00

According to the documentation for MQFMT_IMS_VAR_STRING, MQ uses the Encoding field to interpret the first two bytes (LL), but not the next two bytes (ZZ).


I will look at your suggestions and make modifications to the code I'm using. Again thank you so much and to everyone else for the help! I don't think I would have gotten things to work without the help!
Gary
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic  Reply to topic Goto page Previous  1, 2 Page 2 of 2

MQSeries.net Forum Index » General IBM MQ Support » Coding LLZZ IMS header in C++
Jump to:  



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.