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()
Related
Is there a single standard C/C++ function which takes either a file handle/pointer or a pointer to an in-memory buffer and reads data from the file/buffer?
I have a function which pulls data from a file, performs operations on said data, and sends it out over a socket. I also have a function that takes data in the form of a char buffer, performs exactly the same operations on that data, and sends it over a socket. This problem isn't that hard. I just thought it would be convenient if there was a function like
read(void *dest, void *src, int src_type, size_t amount)
In C++ you can use std::istream as an abstraction on top of a file with an std::ifstream implementation, or an in-memory buffer with an std::istringstream implementation.
The beauty of this approach is that your function does not need to know about the implementation type, because receiving the argument by reference would be sufficient:
void readData(std::istream& in_data) {
...
}
The caller would then construct an appropriate implementation, and pass it to readData.
Sounds like you want to use the operator>>() on an input stream (std::istream), which can either be a filestream, a iostream or a stringstream
I don't know about windows but it will work in Linux.
void readif(int fd ,char *src,size_t nbytes){
read(fd,src,nbytes);
//error handler code
//Other stuffs
}
int fd = open(file);
//for std::input fd = 0
//for in memory data use mmap
mmap
open
read
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.
I am developing a plug-in for two 3rd party programs: A and B in C++ on Windows (7) and need a robust, relatively simple (and fast) way to communicate between the two programs.
The communication is one way: based on user interaction in program A I want my plug-in inside program A to send a signal that ends up calling a function inside my plug-in in program B.
The protocol is simple. This is the signature of the receiving function inside my plug-in in B:
struct XYZ {
double x, y, z;
}
void polyLineSelected(long id, std::vector<XYZ> & points);
How would you recommend to do this?
By far the easiest way to implement one-way communication on Windows is to send a WM_COPYDATA message. It takes a COPYDATASTRUCT parameter to move arbitrary data from one application to another.
For your specific example an implementation of the sender would look like this:
// Declare symbolic constants to identify data
enum DataType {
DataType_Points
};
// Declare struct to hold compound data
struct IPCData {
long id;
XYZ pts[];
};
// Allocate buffer
const size_t bufferSize = offsetof(IPCData, pts[points.size()]);
vector<char> buffer(bufferSize);
IPCData* pData = reinterpret_cast<IPCData*>(&buffer[0]);
// Fill the buffer
pData->id = 42;
copy(points.begin(), points.end(), &pData->pts[0]);
// Prepare COPYDDATASTRUCT
COPYDATASTRUCT cds = { 0 };
cds.dwData = DataType_Points; // Can be used by the receiver to identify data
cds.cbData = bufferSize;
cds.lpData = pData;
// Send the data
SendMessage(hWndRecv, WM_COPYDATA,
(WPARAM)hWndSender,
(LPARAM)(LPVOID)&cds);
I am trying to create C-style structs in Clojure, so I can call a poorly documented C++ API from Clojure.
The API is designed to send and receive serialized protobuf messages (the good) preceded by a C Header struct (the bad). The initial handshake is an RPCHandshakeHeader struct and the process is roughly described in the code below:
struct RPCHandshakeHeader {
char magic[8];
int version;
static const char REQUEST_MAGIC[9];
static const char RESPONSE_MAGIC[9];
};
[...snip...]
const char RPCHandshakeHeader::REQUEST_MAGIC[9] = "FooBar?\n";
[...snip...]
RPCHandshakeHeader header;
memcpy(header.magic, RPCHandshakeHeader::REQUEST_MAGIC, sizeof(header.magic));
header.version = 1;
socket = new CActiveSocket();
socket->Initialize();
socket->Open((const uint8 *)"localhost", 5000);
socket->Send((uint8*)&header, sizeof(header));
[...code to read response...]
How can I do this in clojure? Do I need to use JNA/JNI?
Is there a way to create a C struct, turn it into binary and send it over a socket? (I think this is what I need to do)
Sounds like a job for gloss! I don't know the details of this part of the API, but you want to look particularly at compile-frame, and repeated for the character strings.
I'm currently working on a small project: there's a protocol for sending some strings via UDP implemented with standard C interface.
Although it works pretty fine, I'd like to rewrite it with some more sophisticated C++ (consider it exercise).
Currently it's something like that: A client wants that string so it sends the following struct:
struct request {
uint8_t msg_type;// == 1
uint64_t key; // generated randomly to identify each request
}
In new implementation, I want to use boost::asio so in server I have a following piece of code:
boost::asio::io_service io_service;
boost::asio::ip::udp::endpoint client_endpoint;
boost::asio::ip::udp::socket socket(io_service,
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(),
m_serverPort));
boost::asio::streambuf sb;
boost::asio::streambuf::mutable_buffers_type mutableBuf =
sb.prepare(sizeof(request));
size_t received_bytes = socket.receive_from(mutableBuf, client_endpoint);
sb.commit(received_bytes);
request r;
std::istream is(&sb);
is >> msg_type;
is >> key;
key = __bswap64(key); // I'm using network byteorder for numbers sent with this protocol
// and there's no ntohll function on Snow Leopard (at least I can't
// find one)
sb.consume(received_bytes);
And here's my problem: the "key" value which I try to receive this way is wrong - I mean I get something that I did not send.
Here are my suspicions:
__bswap64 does not convert network to host (little-endian) byteorder
I misunderstood how to use boost::asio::streambuf with streams
There's some incompatibility between old C interface and boost (but I don't think so
cause I've found out that boost functions are just wrappers for it)
EDIT:
hmm they say "don't praise a ford till you get over". Now I have a very similar issue in another place of my code. I have a following struct which is sent as a reply for request metioned above:
struct __attribute__ ((packed)) CITE_MSG_T
{
uint8_t msg_id;
uint64_t key; // must be the same as in request
uint16_t index; // part number
uint16_t parts; // number of all parts
CITE_PART_T text; // message being sent
};
//where CITE_PART_T is:
struct __attribute__ ((packed)) CITE_PART_T
{
uint16_t data_length;
char* data;
};
and following piece of code: http://pastebin.com/eTzq6AWQ.
Unfortunately there's another bug in it and again I read something I haven't sent - replyMsg.parts and replyMsg.index is always 0 although old implementation says they're for example 3 and 10. What's wrong this time? As you can see I take care of padding and I use read instead of operator>>. If you wonder why I read that struct field by field here's an answer: A server sends two different structures, both beginning with msg_id, one if it succeceeds and another if it fails. Right now, I simply have no idea how to do it other way.
You're using formatted input, as though the data being sent were textual -- you need unformatted input. Read about the std::istream::read member function, as it's what you should be using rather than operator>>.
Note that this would have been immediately obvious if you had been checking the stream state after each extraction, as one always should in non-throw-away code.
You forgot about padding. Your request structure probably has at least three bytes inserted by the compiler between the first and the second member, as in:
struct request {
uint8_t msg_type;
char __pad__[3]; // or 7 on 64-bit machine.
uint64_t key;
};
You can fix that, say in GCC, with attributes (see the GCC manual):
struct __attribute__ ((__packed__)) request { ...
And yes, I did miss the fact that you are trying to read text instead of binary. Fix that first, get bitten by alignment/padding later :)