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.
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.
Related
I am programming an ESP32 in the Arduino framework. For my application, I need to create a buffer which will store information from both the present and the last time it was accessed. Here is what I am attempting to do.
//first buffer
char buffer1[4];
//second buffer
char buffer2[8];
void setup {
//setup
}
//buffer1 values will change with each iteration of loop from external inputs
//buffer2 must store most recent values of buffer1 plus values of buffer1 from when loop last ran
for example:
**loop first iteration**
void loop {
buffer1[0] = {1};
buffer1[1] = {2};
buffer1[2] = {3};
buffer1[3] = {1};
saveold(); //this is the function I'm trying to implement to save values to buffer2 in an element-wise way
}
//value of buffer2 should now be: buffer2 = {1,2,3,1,0,0,0,0}
**loop second iteration**
void loop {
buffer1[0] = {2};
buffer1[1] = {3};
buffer1[2] = {4};
buffer1[3] = {2};
saveold();
}
//value of buffer2 should now be: buffer2 = {2,3,4,2,1,2,3,1}
From what I've been able to understand through searching online, the "saveold" function I'm trying to make
should implement some form of memmove for these array operations
I've tried to piece it together, but I always overwrite the value of buffer2 instead of somehow shifting new values in, while retaining the old ones
This is all I've got:
void saveold() {
memmove(&buffer2[0], &buffer1[0], (sizeof(buffer1[0]) * 4));
}
From my understanding, this copies buffer1 starting from index position 0 to buffer2, starting at index position 0, for 4 bytes (where 1 char = 1 byte).
Computer science is not my backround, so perhaps there is some fundamental solution or strategy that I am missing. Any pointers would be appreciated.
You have multiple options to implement saveold():
Solution 1
void saveold() {
// "shift" lower half into upper half, saving recent values (actually it's a copy)
buffer2[4] = buffer2[0];
buffer2[5] = buffer2[1];
buffer2[6] = buffer2[2];
buffer2[7] = buffer2[3];
// copy current values
buffer2[0] = buffer[0];
buffer2[1] = buffer[1];
buffer2[2] = buffer[2];
buffer2[3] = buffer[3];
}
Solution 2
void saveold() {
// "shift" lower half into upper half, saving recent values (actually it's a copy)
memcpy(buffer2 + 4, buffer2 + 0, 4 * sizeof buffer2[0]);
// copy current values
memcpy(buffer2 + 0, buffer1, 4 * sizeof buffer1[0]);
}
Some notes
There are even more ways to do it. Anyway, choose the one you understand best.
Be sure that buffer2 is exactly double size of buffer1.
memcpy() can be used safely if source and destination don't overlap. memmove() checks for overlaps and reacts accordingly.
&buffer1[0] is the same as buffer1 + 0. Feel free to use the expression you better understand.
sizeof is an operator, not a function. So sizeof buffer[0] evaluates to the size of buffer[0]. A common and most accepted expression to calculate the size of an array dimension is sizeof buffer1 / sizeof buffer1[0]. You only need parentheses if you evaluate the size of a data type, like sizeof (int).
Solution 3
The last note leads directly to this improvement of solution 1:
void saveold() {
// "shift" lower half into upper half, saving recent values
size_t size = sizeof buffer2 / sizeof buffer2[0];
for (int i = 0; i < size / 2; ++i) {
buffer2[size / 2 + i] = buffer2[i];
}
// copy current values
for (int i = 0; i < size / 2; ++i) {
buffer2[i] = buffer1[i];
}
}
To apply this knowledge to solution 2 is left as an exercise for you. ;-)
The correct way to do this is to use buffer pointers, not by doing hard-copy backups. Doing hardcopies with memcpy is particularly bad on slow legacy microcontrollers such as AVR. Not quite sure what MCU this ESP32 got, seems to be some oddball one from Tensilica. Anyway, this answer applies universally for any processor where you have more data than CPU data word length.
perhaps there is some fundamental solution or strategy that I am missing.
Indeed - it really sounds that what you are looking for is a ring buffer. That is, an array of fixed size which has a pointer to the beginning of the valid data, and another pointer at the end of the data. You move the pointers, not the data. This is much more efficient both in terms of execution speed and RAM usage, compared to making naive hardcopies with memcpy.
I want to find the number of running processes using EnumProcesses function from psapi library. The function requieres an array that will receive the list of process identifiers. It also writes the total number of bytes of found data into a given variable. I didn't want the process list, just their number. I did the following.
DWORD listSize;
DWORD a;
EnumProcesses( &a, 1000*sizeof(DWORD), &listSize ) ;
listSize/=sizeof(DWORD);
printf("%d",listSize);
This writes the real number of processes into listSize however the program stops working after that. I was wondering if there is a way to immediately send the retrieved data into oblivion and just get the number of it.
Not possible. However providing a big enough array isn't really much of an issue on modern systems.
I recommend writing a helper function that wraps this all away for you with a dynamically sized container, so you can handle cases where more processes exist than your original array can hold:
DWORD GetNumberOfProcesses()
{
std::vector<DWORD> processes;
DWORD size = 0;
DWORD bytesReturned = 0;
while (bytesReturned == size)
{
size += 1024 * sizeof(DWORD);
processes.resize(size / sizeof(DWORD));
if (!EnumProcesses(processes.data(), size, &bytesReturned))
{
return -1;
}
}
return bytesReturned / sizeof(DWORD);
}
I am working with the SystemC TLM library. I would like to send a payload with two integers to a module that will perform an operation on those two integers. My question is simply how to setup and decode the payload.
Doulos provided documentation on both setting up and decoding here https://www.doulos.com/knowhow/systemc/tlm2/tutorial__1/
Setup
tlm::tlm_command cmd = static_cast(rand() % 2);
if (cmd == tlm::TLM_WRITE_COMMAND) data = 0xFF000000 | i;
trans->set_command( cmd );
trans->set_address( i );
trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) );
trans->set_data_length( 4 );
trans->set_streaming_width( 4 );
trans->set_byte_enable_ptr( 0 );
trans->set_dmi_allowed( false );
trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
socket->b_transport( *trans, delay );
Decode
virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
{
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address() / 4;
unsigned char* ptr = trans.get_data_ptr();
unsigned int len = trans.get_data_length();
unsigned char* byt = trans.get_byte_enable_ptr();
unsigned int wid = trans.get_streaming_width();
So it looks to me like you would send a pointer to a memory location where there are two integers written.
|----------------------------------int1-------------------------|------------------------------------int2------------------------
|ptr+0x0|ptr+0x(wid)|ptr+0x(2*wid)|ptr+0x(3*wid) | ptr+0x(4*wid)|ptr+0x(5*wid)|ptr+0x(6*wid)|ptr+0x
----------|
(7*wid)|
Is my interpretation of this documentation correct?
How could you get those first 4 memory locations [3:0] and combine them into an int32 and how could you get the second 4 [7:4] and turn them into the second integer?
So it looks to me like you would send a pointer to a memory location
where there are two integers written.
Is my interpretation of this documentation correct?
Yes
To get them back you just need to copy them:
int32_t val0, val1;
memcpy(&val0, ptr, sizeof(int32_t));
memcpy(&val1, ptr + sizeof(int32_t), sizeof(int32_t));
or something like
int32_t val[2];
memcpy(val, ptr, sizeof val);
But make sure initiator keeps memory under the pointer valid long enough e.g. it might be better to avoid using keep data on the stack. And don't forget to check if payloads data length attribute has valid value - you want to detect those issues as soon as possible.
I'm trying to write a image via UART on Beaglebone Black. But when I use the write() function in library .
int write(int handle, void *buffer, int nbyte);
Regardless of the agurment nbyte has int type, I can not transfer 70kB at once. I displayed the number of byte which is transfered, and the result is the number of byte = 4111.
length = write(fd,body.c_str(),strlen(body.c_str())); //
cout<<length<<endl; // result length = 4111;
cout<<strlen(body.c_str())<<endl; // result strlen(body.c_str()) = 72255;
I hope to hear from you!
The write call does not assure that you can write the amount of data supplied, that's why it as an integer as its return, not a Boolean. The behavior you see is actually common among different operating systems, it may be due to the underline device might does not have sufficient buffer or storage for you to write 70kb. What you need is to write in a loop, each write will write the amount that is left unwritten:
int total = body.length(); // or strlen(body.c_str())
char *buffer = body.c_str();
int written = 0;
int ret;
while (written < total) {
ret = write(fd, buffer + written, total - written);
if (ret < 0) {
// error
break;
}
written += ret;
}
I am sending the data from a file using the Libcurl post callback. The example here shows, how to send data as 1 byte per call from callback function.
I have changed the code so the file is read into chunks. That pretty much works fine.
the current sample code is:
if(sizeleft){
*( char *)ptr = readptr[0];
readptr++;
sizeleft--;
return 1;
}
This example sends the data as 1 byte.
but suppose i have to send it multiple bytes.I have tried to increment readptr by two each time and decreasing sizeleft by two and i return 2bytes at a time.
It didnt work like this and the data is corrupted.
I would appreciate if someone out there could help me out.
Thank you
It's difficult to tell from your question exactly what you're doing, exactly what you'd expect to happen and exactly what actually happens. However it looks like you're on the right track.
The documentation for CURLOPT_READFUNCTION states that size * nitems (a.k.a. size * nmemb in the example) is the upper limit of the number of bytes you may write into buffer, and the return value of your function is the actual number of bytes that you wrote. Returning zero means that you have written everything you wish to write, and your callback function won't be called any more.
If the value you return from your function does not equal the number of bytes that you actually wrote into the buffer, then you can expect corruption.
PS: Something like:
// copy as many bytes as we can, up to either:
// * The number of bytes we have remaining.
// or
// * The space available in ptr.
size_t maxBytes = size * nmemb;
size_t numBytes = std::min (maxBytes, sizeleft);
memcpy (ptr, readptr, numBytes);
readptr += numBytes;
sizeleft -= numBytes;
return numBytes;