How to send a structure as data on UDP using SendBuffer? - c++

typedef struct
{
char cStartByte; // Set Cmd 0xB1
int iTotalBytes;
char cSeqNum; // 0 to 99 repeating
char cCommand; //
char cPrintCmd; //
float fData[8]
} CMD,*psCmdOut;
In the code tried many options with no success what to put in ??? to sedn the above structure?
UDPClient1->SendBuffer(EHost->Text,12000, ????);

You can't send your structure as-is using a socket : you need to serialize it. You need to create a common format for data exchange, usually an array of char like this one.
Code :
unsigned char* ToCharArray(psCmdOut s)
{
unsigned char serial[12]; //32-bit arch
serial[0] = s.cStartByte;
/*etc.*/
return serial;
}
You can cast your structure in a (char*) back and forth , but I would advise strongly against it : the implicit conversion hides subtleties like endianness, internal memory padding and alignment, which can blow your system in a unpredictable way.

The answer depends on your version of Indy.
In Indy 8 and 9, SendBuffer() has the following signture:
void __fastcall SendBuffer(String AHost, const int APort, void* ABuffer, const int AByteCount);
So you can do this:
CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, &cmd, sizeof(cmd));
In Indy 10, SendBuffer() was changed to take a TIdBytes (dynamic array of bytes) instead:
void __fastcall SendBuffer(const String AHost, const TIdPort APort, const TIdBytes ABuffer);
So you cannot pass the struct pointer directly anymore. However, Indy 10 has a RawToBytes() function to create a TIdBytes from a memory block, so you can do this instead:
CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, RawToBytes(&cmd, sizeof(cmd)));

As the #Sam suggested:
UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast(&cmd_command));
But the length of the structure is also required. So it will be:
UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast<char*>(&cmd_command), sizeof(cmd_command));
And also I think it will be better if you do packing of the structure by adding
#pragma pack(1)
This will give you the actual size of the structure. With this you will be able to send the complete structure. And while receiving on the other side, typecast it back to the same structure.

Related

C++ Named Pipe WriteFileEx / ReadFile, unicode / ansi

I am trying to pass data from an x64 app to a x86 app using named pipes and overlapped I/O like what is defined here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx
My server application's call to WriteFileEx succeeds and the structure I am sending through the pipe seems ok, however when I call ReadFile on the client side the data structure I retrieve is corrupted or different to the data that I sent, but it also successfully reads.
My client application has a unicode character set and the server's character set is 'not set', which I assume defaults to multibyte. I'm not in a position to change the server's character set to unicode.
Would this data corruption just be because I need to convert from multibyte to wide char on the client after I retrieve / read the data structure? If so is there built in helper functions that I can call on do to that?
Data structure being sent (defined identically on the server and client):
typedef struct
{
int id;
float vertices[VERTICES_COUNT][VERTICES_COMPONENTS];
unsigned short indices[INDICES_COUNT];
float texCoords[TEXTURE_COORD_COUNT][TEXTURE_COORD_COMPONENT];
unsigned char texData[TEXTURE_SIZE];
} MESHINST, *LPMESHINST;
typedef struct
{
OVERLAPPED oOverlap;
HANDLE pipeInst;
int addedCount;
MESHINST meshes[MESH_GROUP_BUFFER];
int removedCount;
int removed[MESH_REMOVE_BUFFER];
} MESHGROUPINST, *LPMESHGROUPINST;
WriteFileEx call on the server:
LPMESHGROUPINST meshes = (LPMESHGROUPINST)lpOverLap;
fWrite = WriteFileEx(
meshes->pipeInst,
(wchar_t*)meshes,
sizeof(MESHGROUPINST),
(LPOVERLAPPED)meshes,
(LPOVERLAPPED_COMPLETION_ROUTINE)CompletedWriteRoutine);
ReadFile call on the client:
(in header)
MESHGROUPINST _meshes;
(in cpp)
do
{
_success = ReadFile(
_pipe,
(wchar_t*)&_meshes,
sizeof(MESHGROUPINST),
&_numOfBytesRead,
NULL);
} while (!_success);
What is the type of _meshes in the ReadFile call? If it's a pointer, you'll be reading into the pointer, not the data being pointed to:
&_meshes
Should be:
_meshes
Also, it looks like you're writing process-specific HANDLE and OVERLAPPED info. Did you mean to write those?
You'll need to add more code for better help.
You need to ensure the structure is sent and received with 1-byte packing. Use #pragma pack(1) around the struct you wish to send/receive:
#pragma pack(1)
typedef struct
{
int id;
float vertices[VERTICES_COUNT][VERTICES_COMPONENTS];
unsigned short indices[INDICES_COUNT];
float texCoords[TEXTURE_COORD_COUNT][TEXTURE_COORD_COMPONENT];
unsigned char texData[TEXTURE_SIZE];
} MESHINST, *LPMESHINST;
#pragma pack()

Passing array of stuct to kernel results in segfault on write?

Maybe I missed something from the tutorials because this is driving me nuts.
What I'm trying to accomplish: I want to create an array of structs for the OpenCL device to use as a work area. The host doesn't need to see it or interact with it in any way, it's just meant as a "scratch" space for the kernel to work within.
Here's what I have:
Declaration of struct inside header file accessible by both the main program and the OpenCL kernel:
typedef struct {
uint64_t a;
uint32_t b;
} result_list;
Initializing the scratch space buffer "outputBuffer" to hold MAX_SIZE elements:
cl_mem outputBuffer;
outputBuffer = clCreateBuffer(this->context,
CL_MEM_READ_WRITE,
sizeof(result_list) * MAX_SIZE,
NULL,
&status);
I never call clEnqueueWriteBuffer because the host doesn't care what the memory is. It's simply meant to be a working space for the kernel. I leave it as uninitialized but allocated.
Setting it as an argument for the kernel to use:
status = clSetKernelArg(myKernel,
1,
sizeof(cl_mem),
&this->outputBuffer);
The kernel (simplified to remove non-issue sections):
__kernel void kernelFunc(__global const uint32_t *input, __global result_list *outputBuffer) {
if (get_global_id(0) >= MAX_SIZE) { return; }
// Make a few local variables and play with them
outputBuffer[0].a = 1234; // Memory access violation here
// Code never reaches here
}
What am I doing wrong?
I installed CodeXL from AMD and it doesn't help much with debugging issues like these. The most it gives me is "The thread tried to read from or write to a virtual address to which it does not have access."
edit: It seems like it really doesn't like typedefs. Instead of using a struct, I simplified it to typedef uint64_t result_list and it refused to compile, saying "a value of type 'ulong' cannot be assigned to an entity of type 'result_list'", even though result_list -> uint64_t -> unsigned long.
Your problem is that you cannot put in a single header both definitions for HOST and DEVICE.
You have to separate them like this:
//HOST header
struct mystruct{
cl_ulong a;
cl_uint b;
};
//DEVICE header
typedef struct{
ulong a;
uint b;
} mystruct;
Notice that I also changed the datatype to the standar OpenCL datatypes. You should use those instead for compatibility.

Howto serialize and deserialize between unknown typedef struct and QByteArray

I am an absolute beginner to C++ and Qt.
I am broadcasting different data via TCP using Qt. The process of sending and retrieving data works fine but I have problems on interpreting the data on the receivers side.
The data is represented in different structs which have in common that they have a commandId and a state. The rest could be anything like an error message, a filename or something else. This code is not written on my own and I am not allowed to change it (e.g: define and implement a common interfaces.)
typedef struct
{
uint8_t commandId;
State state;
//special data
QString errorMessage;
} Command1;
typedef struct
{
uint8_t commandId;
State state;
//special data
uint8_t amountSensors;
} Command2;
enum State {
STATID_PAUSE = 50000
STATID_RECORD = 50001
STATID_PLAY = 50002
STATID_ERROR = 50003
}
The sender is converting a struct into a QByteArray this way:
Command1 example;
example.commandId = 134;
example.state = STATID_ERROR;
char *p_Char;
p_char = reinterpret_cast<char*>(&example);
QByteArray qba(p_char, sizeof(p_char));
Now I have to write a receiver, but the receiver doesn't know what he gets (Command1, Command2 or something else). He would be able to interpret if he could read out the commandId and the state.
At this moment I am able to read out the commandId like this:
commandId = static_cast<uint8_t>(qba[0]);
but how could I read out the State which is an enum?
State values will take the size of an int. which means to access it you will do :
State state = (State) (*( reinterpret_cast<const int*>(qba.constData()+1)) );
First you reinterpret the const char pointer as an const int pointer, then you deference it (which means you obtain the value), and you cast this value as an State.
In order to access other variables you will start at index 1 + sizeof(int) = 1+ sizeof(State)
See this thread about the size of an enum.

Accessing the member of a class that is part of a WiFi listener callback member function

I have a WiFi Listener registered as a callback (pointer function) with a fixed 3rd party interface. I used a static member of my function to register the callback function and then that static function calls a nonstatic member through a static cast. The main problem is that I cannot touch the resulting char * buff with any members of my class nor can I even change an int flag that is also a member of my class. All result in runtime access violations. What can I do? Please see some of my code below. Other problems are described after the code.
void *pt2Object;
TextWiFiCommunication::TextWiFiCommunication()
{
networkDeviceListen.rawCallback = ReceiveMessage_thunkB;
/* some other initializing */
}
int TextWiFiCommunication::ReceiveMessage_thunkB(int eventType, NETWORK_DEVICE *networkDevice)
{
if (eventType == TCP_CLIENT_DATA_READY)
static_cast<TextWiFiCommunication *>(pt2Object)->ReceiveMessageB(eventType,networkDevice);
return 1;
}
int TextWiFiCommunication::ReceiveMessageB(int eventType, NETWORK_DEVICE *networkDevice)
{
unsigned char outputBuffer[8];
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
tempString.erase(tempString.size()-8,8); //funny thing happens the outputBuffer is double in size and have no idea why
if (tempString.compare("facereco") == 0)
cmdflag = 1;
return 1;
}
So I can't change the variable cmdflag without an access violation during runtime. I can't declare outputBuffer as a class member because nothing gets written to it so I have to do it within the function. I can't copy the outputBuffer to a string type member of my class. The debugger shows me strlen.asm code. No idea why. How can I get around this? I seem to be imprisoned in this function ReceiveMessageB.
Thanks in advance!
Some other bizzare issues include: Even though I call a buffer size of 8. When I take outputBuffer and initialize a string with it, the string has a size of 16.
You are likely getting an access violation because p2tObject does not point to a valid object but to garbage. When is p2tObject initialized? To what does it point?
For this to work, your code should look something like this:
...
TextWifiCommunication twc;
p2tObject = reinterpret_cast<void*>(&twc);
...
Regarding the string error, TCP_readData is not likely to null-terminate the character array you give it. A C-string ends at the first '\0' (null) character. When you convert the C-string to a std::string, the std::string copies bytes from the C-string pointer until it finds the null terminator. In your case, it happens to find it after 16 characters.
To read up to 8 character from a TCP byte stream, the buffer should be 9 characters long and all the bytes of the buffer should be initialized to '\0':
...
unsigned char outputBuffer[9] = { 0 };
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
...

C++ TLS, somethings wrong

I'm learning about Thread Local Storage... (TLS)
Here is my TLS Alloc code:
//global variable
DWORD g_dwTlsIndex;
//inside DLLMain:
int val= 5;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_dwTlsIndex = TlsAlloc();
if ((g_dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
{
printf("No more indexes available");
}
void *pint;
memcpy(&pint, &val, sizeof val);
TlsSetValue(g_dwTlsIndex, pint);
break;
Now I try to get the value from the TLS: (in another CPP file)
// declare index value...
extern DWORD g_dwTlsIndex;
int data;
LPVOID d;
d = TlsGetValue(g_dwTlsIndex);
memcpy(&data, &d, sizeof d);
printf("Data: %d", data);
But data contains 0, where I put 5 in it.... What have I done wrong?
A few notes:
Your error checking statement should read:
if (g_dwTLSIndex == TLS_OUT_OF_INDEXES).
As it stands, you're assigning g_dwTlsIndex twice (and thus losing the reference with the first assignment.)
Do some basic debugging:
Call TlsGetValue in the line immiediately after TlsSetValue. Does that work at least?
Check the return codes. TlsGetValue and TlsSetValue both return a function telling you whether the assignment was successful. Was it?
Keep track of your index. You're using a global variable to store g_dwTlsIndex, so it could easily be getting altered. What is the value after alloc (use a printf to see). What is the value when you make the Get call? Do these values match?
These steps should help you find the problem.
I assume that val is local to DllMain?
What version of Windows are you running? 64-bit Windows has 64-bit pointers and 32-bit int, so all the memcpy calls will be incorrect. Rather than using memcpy, just cast the values directly:
TlsSetValue(g_dwTLSIndex,(LPVOID)5);
int data=(int)TlsGetValue(g_dwTLSIndex);