0

So after a bunch of research I found that using WideCharToMultiByte worked great for sending data from the Control Object through OPOS to my custom SO. well we encountered a bug. In the DirectIO portion the C# Control Object's map is DirectIO(int command, ref int data, ref string object);

and for the longest we only needed to send simple commands through DirectIO. For instance to turn on the LED we would set the data to be the length in milleseconds, and the object to be the color. When we needed to write data to a tag or a card the text had to be parsed from a special XML styled string to a byte array... well now the need has come about that we need to have a byte array, use ASCII encoding to put that array into string form, and have it write..

The problem comes around that when I convert this string in my Service Object it doesn't convert it right. it seems to stop on null, even though SysStringLen knows the length is 4bytes. example The control object does this

        int page = 16;
        byte[] data = new byte[] { 0x19, 0x00, 0x30, 0x00 };
        string pData = System.Text.ASCIIEncoding.ASCII.GetString(data);
        msr.DirectIO(902, ref page, ref pData);

The SO sees this

int len = (int)SysStringLen(*pString);
long dataData = *pData;
char* dataObject = new char[1+len];

WideCharToMultiByte(CP_ACP, 0, *pString, -1, dataObject, len, NULL, NULL);
ByteUtil::LogArray("dataObject", (BYTE*)dataObject, len);

yields the output of

dataObject(4)-19:00:00:00

basically as soon as teh first null character is reached the rest of the data is lost. now if i convert the number from a string to a string it works out ok because I have a ByteUtil function just for that occasion... but it doesn't seem right for me to have to do that... why can't i just have it as a BYTE array?

Robert Snyder
  • 2,399
  • 4
  • 33
  • 65
  • I think i maybe just answered my own question in that a different type of card that we write too we send a string that represents a byte array and convert it... so we should just stick with that method... and that matches the OPOS standards anyway... but if anyone has a suggestion please feel free to tell me :) – Robert Snyder Feb 10 '13 at 20:18

1 Answers1

2

Very easy, just change this line:

WideCharToMultiByte(CP_ACP, 0, *pString, -1, dataObject, len, NULL, NULL);

into:

WideCharToMultiByte(CP_ACP, 0, *pString, len, dataObject, len, NULL, NULL);

If you set the fourth parameter to -1, WideCharToMultiByte treats the input string as a null-terminated string. BSTRs are null-terminated for compatibility reasons, but you should never treat them as null-terminated because they can contain null characters as part of the string.

user1610015
  • 6,561
  • 2
  • 15
  • 18
  • wow, thank you for pwning me :) hahaha so on this note then if the value is a string should I end it with a null or will widechartomultibyte do that for me? I ask because I don't want to have a 5byte array when it is really a 4 byte array.. but obviously for a string i need that ending null right? – Robert Snyder Feb 11 '13 at 01:07
  • 1
    That's expained in the MSDN documentation for WideCharToMultiByte. The output string will be null-terminated if you pass -1 as the cchWideChar parameter (which of course means that you need to pass a null-terminated input string), or if the input string contains a null character within the length you pass as cchWideChar. Anyway, in this case it doesn't make much sense to null-terminate it because there are null characters as part of the string. Besides, null-terminated strings are bad in general, you should use length-prefixed strings like BSTR, or string classes like std::string, CString, etc – user1610015 Feb 11 '13 at 01:30