0

I am trying to send (ideally) a 2d buffer from one process to another, over a Message Queue, but i am attempting to do it first with a 1d buffer.

The functions called to initialization the queue are the following:

HANDLE MsgQueueCommunicator::InitMessageQueue_data(bool IsRead,wchar16_t* wQueueName)
{

  MSGQUEUEOPTIONS msgopts;
  msgopts.dwSize        = sizeof(MSGQUEUEOPTIONS);   
  msgopts.dwFlags       = MSGQUEUE_ALLOW_BROKEN;//0;
  msgopts.dwMaxMessages = 0;
  msgopts.cbMaxMessage  = sizeof(data[20]);   
  msgopts.bReadAccess   = IsRead;   

  HANDLE hq = CreateMsgQueue(wQueueName, &msgopts);
  if ( hq == NULL )   
  {    
      return NULL;
  }   
  return hq;
}

Queue initialization in process 1:

 HANDLE hMsgQueueR = MsgQueueCommunicator::getInstance()->InitMessageQueue_data(true, L"CommDataStreaming");

Queue initialization in process 2:

 HANDLE s_hMsgQueue_Communication = MsgQueueCommunicator::getInstance()->InitMessageQueue_data(false,L"CommDataStreaming");

To write to the queue, i call the following functions:

BOOL MsgQueueCommunicator::Write_Array_To_Queue(HANDLE hq,double data[20])
{
    return WriteMsgQueue(hq,(LPVOID)&data, sizeof(data),INFINITE,0);
}

MsgQueueCommunicator::getInstance()->Write_Array_To_Queue(s_hMsgQueue_Communication, usb_data);

Where usb_data is a 1d double array.

To read from the queue, i call the following functions:

BOOL MsgQueueCommunicator::Read_Array_From_Msg_Queue(HANDLE hq,double data[20])
{
    DWORD dwBytesRead;
    DWORD dwFlags;
    return ReadMsgQueue(hq, (LPVOID)&data, sizeof(data), &dwBytesRead, INFINITE, &dwFlags);
}

MsgQueueCommunicator::getInstance()->Read_Array_From_Msg_Queue(hMsgQueueR, usb_data);

Where usb_data is again a 1d double array.

Now, when i check the values that are placed into usb_data[20] before it is written to the queue, i can see that they are non-zero integers. However, when i read the array from the queue and check its values, they are zero. Im not sure what is causing this issue. I've used message queues to send single values, strings, and structs, so i figured i would be able to follow the same procedure to send over an array, but this does not seem to be the case, unless i am overlooking something.

My question is, can i send arrays/buffers over a message queue, and if yes, have I set it up properly?

Note:This is being developed in a windows embedded compact 7 environment and VS2008.

Javia1492
  • 862
  • 11
  • 28
  • Does dwBytesRead return the expected value (20, I'm guessing?). I am suspicious of sizeof(data) in ReadMsgQueue, since it may be returning the size of a pointer, which is 4 instead of 20, but I'm unsure. – walkingTarget Aug 18 '15 at 15:49
  • 1
    Is `(LPVOID)&data` needed? Isn't `(LPVOID)data` enough since it already is a pointer to the beginning of the memory block with the doubles? – Rudolfs Bundulis Aug 18 '15 at 15:54
  • I concur with @Rudolfs Bundulis. I think if you combine our two comments you'll see success. – walkingTarget Aug 18 '15 at 16:01
  • @RudolfsBundulis I didnt think of that. That may be related to the issue. I will try not using the reference and see what happens. – Javia1492 Aug 18 '15 at 16:01
  • @walkingTarget he doesn't need to send 20 bytes but 160 bytes and since the size of the array is set at the parameter declaration `sizeof` will correctly return 160. It would give 4 for a `double*` or `double[]`. – Rudolfs Bundulis Aug 18 '15 at 16:01
  • @Javia1492 I think that should be it ;) If you succeed I can post this as an answer. But if I am correct it is weird that you did not get any access violations since you are going into random memory with dirty hands. – Rudolfs Bundulis Aug 18 '15 at 16:03
  • @RudolfsBundulis You are correct that it should be 160 bytes for a double, but I maintain that sizeof will return the size of a pointer. – walkingTarget Aug 18 '15 at 16:04
  • @walkingTarget true, I for some reason forgot that this is not a stack variable but a function call, don't mind me. – Rudolfs Bundulis Aug 18 '15 at 16:17
  • @RudolfsBundulis Im still getting the same result as before. – Javia1492 Aug 18 '15 at 18:14
  • And if you combine what I said with fixing the buffer size (just try hardcoding 160 for now) does it help? Since now you are still most likely sending over only 4 bytes and reading 4 as well. – Rudolfs Bundulis Aug 19 '15 at 08:50
  • @RudolfsBundulis Awesome, hardcoding it has worked. Now, ideally what i would like to do is not have the buffer size hardcoded since i plan to use various buffer sizes for different situations. Would it be easier to just have different read/write functions (although it would seem redundant and not very efficient). – Javia1492 Aug 19 '15 at 15:05
  • @Javia1492 I'll make a full answer regarding this as well since it's too long for a comment. – Rudolfs Bundulis Aug 19 '15 at 15:06

1 Answers1

1

There are several problems with the code provided.

1) Wrong parameter values - you do not need to take an address of the data buffer since the variable is already a pointer to the beginning of the memory that contains the elements. So change (LPVOID)&data to (LPVOID)data.

2) Wrong size - the sizeof operator will return 4 since that is the size of the pointer. In your case you would need to pass 160 as the size (20 * sizeof(double)).

As for variable size writes - this gets a bit more complicated since you need to know how much data to read at the other end. What you can do is use lets say first/first two/first four bytes of the buffer to contain size and then proceed with the data. Then you can have a function that accepts a double array of variable length and writes it. For example:

BOOL Write_Array_To_Queue(HANDLE hq,double data[], unsigned int count)
{
    size_t buffer_size = sizeof(count) + count * sizeof(double);
    BYTE* buffer = new BYTE[buffer_size];
    memcpy(buffer, &count, sizeof(count));
    memcpy(buffer + sizeof(count), &data, sizeof(double) * count);
    return WriteMsgQueue(hq,(LPVOID)buffer, buffer_size,INFINITE,0);
}

or

BOOL Write_Array_To_Queue(HANDLE hq,double data[], unsigned int count)
{
    return WriteMsgQueue(hq,(LPVOID)&count, sizeof(count),INFINITE,0) && WriteMsgQueue(hq,(LPVOID)data, sizeof(double) * count,INFINITE,0);
}

and then in the receiving side you would first read out an unsigned int and then read as much data as denoted by the read value.

Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71
  • The only issue im getting now is occasionally i will read 0's at the end of the buffer but i wrote nonzero values to the buffer. This will be between 1-3 0's. Not sure why its happening. – Javia1492 Aug 19 '15 at 18:39
  • @Javia1492 maybe there are still some size issues? Could it be that you set the write size to larger than the data size and simply copy over some uninitialized memory? Are actually missing a part of the written data? – Rudolfs Bundulis Aug 19 '15 at 20:26
  • If i buffer 20 values, 1-20, and read the buffer after it is writen, there may be a scenario where i get `1,2,3,4,...,16,17,0,0,0`. The data buffer size is 20 and the buffer size for the read/write msgqueue is set to 160. `return WriteMsgQueue(hq,(LPVOID)data, 160,INFINITE,0);` I do not know where it might be copying uninitialized data because i run everything on loop index variables and made sure they do not exceed the number of samples i read/write – Javia1492 Aug 19 '15 at 20:40
  • @Javia1492 do you verify that `dwBytesRead` in `ReadMsgQueue` is equal to 160? I have never used this API but maybe it actually splits the data if it exceeds some internal length? Have you set `cbMaxMessage` when initializing the queue to 160 too? And maybe remove the `MSGQUEUE_ALLOW_BROKEN`? – Rudolfs Bundulis Aug 19 '15 at 20:46
  • @RudolfsBunbulis I do not verify dwBytesRead so im not sure if it splits ithe data or not. Ill try your suggestions and comment with the results, thanks! – Javia1492 Aug 19 '15 at 21:09