Robust, simple (and fast) interprocess communication in C++ on Windows - c++

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);

Related

How to pass Serial object as a number (New library using arduino Serial)

I want to create a new library which controls arduino's Serial library.
Here is what I want ...
main Sketch
#include <newLibrary.h>
newLibrary connection(2,9600); // 2 is Serial2, 9600 is baudRate
void main()
{
connection.start();
}
newLibrary.cpp
newLibrary::newLibrary (uint8_t port, long baudRate)
{
__port = port;
__baudRate = baudRate;
}
void newLibrary::start()
{
(Serial+port).begin(); // I need to add port to Serial to make Serial2
}
What I want to do is,
The user will choose which Serial port(eg. Serial/Serial1/Serial2 etc...) is going to be used with ;
newLibrary connection(2,9600); // 2 is Serial2, 9600 is baudRate
and after that the start function in newLibrary.h will start that Serial port with an algorithm like;
void newLibrary::start()
{
(Serial+port).begin(); // Which is equal to Serial.begin() or Serial1.begin() etc
}
I know it can be done by if statement or switch case...
But is there another way?
Such as macros....
I know that the macros can be used like ;
#define serialPort (Serial##1) // so the serialPort refers to Serial1
But this way doesnt work for me....
C++ doesn't support reflection. You can't build variable names at runtime.
You could store pointers to the objects in a container.
#include <array>
class S {
public:
void begin() {}
} Serial, Serial1, Serial2;
int main() {
std::array serials = {&Serial, &Serial1, &Serial2};
std::uint8_t port = 1;
serials[port]->begin();
}
Instead of taking a uint8_t why don't you take a Stream object and then you can pass Serial2 directly like: newLibrary connection(Serial2,9600);
newLibrary::newLibrary (Stream port, long baudRate)
{
__port = port;
__baudRate = baudRate;
}
newLibrary connection(Serial2,9600);
void newLibrary::start()
{
_port.begin(_baudRate); // Which is equal to Serial.begin() or Serial1.begin() etc
}
Of course you also need to change the line in the class definition that defines _port, but since you didn't post that bit I'll assume you know how to do that.
Moral of the story is, those serial ports are objects of type Stream, so you can pass them around just like variables as long as you use the type Stream instead of int or byte or char.

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()

Sending and receiving structs using UDP (WinSock & C++)?

I have two programs. I need one of them to send data and the other to receive that data.
I have some code in place that is hopefully sending a struct across the network.
However, I don't even know if it is working properly because I don't know how to code the receiving program to receive structs and pass the data it receives into a local struct to be manipulated.
Here is the code I'm using to send if it helps any
gamePacket.PplayerX = userSprite.x;
gamePacket.PplayerY = userSprite.y;
gamePacket.Plives = lives;
gamePacket.Pstate = state;
for(int z=0;z<8;z++)
{
gamePacket.PenemyX[z] = enemySprite[z].x;
gamePacket.PenemyY[z] = enemySprite[z].y;
}
char Buffer[sizeof(gamePacket)];
UDPSocket.Send(Buffer);
The struct is called Packet and gamePacket is an instance of it.
What I am stuck with is:
Is the code I posted even sending the struct
How do I receive the struct in the receiving program so that I can use the data inside it.
Its not send, you only declare a buffer. To send it you need to fill it. Also the way you use sizeof is wrong, it probably doesn't return the right size of all fields, you should count them up.
When you received everything you do the opposite, you allocate a struct and fill it using ofsets
If you need examples just ask. But learning is doing research so an push in the right direction is I think enough. (There are thousand examples on this.)
Ps: you can use pointers + offset because the memory of the struct is layed out next to each other. It are blocks of memory, just like an array.
EDIT; this link is what you need: Passing a structure through Sockets in C
EDIT: Example using pointers:
EDIT: Is this C# or C/C++? I'm sorry if so, change the example to C/C++ ;)
'
struct StructExample
{
int x;
int y;
};
int GetBytes(struct* Struct, void* buf)
{
//Access the memory location and store
*(int*)(buf + 0) = Struct->x;
*(int*)(buf + sizeof(int)) = Struct->y;
return sizeof(Struct->x) + sizeof(Struct->y)
}
Ps: I typed it with my mobile, I'm not 100% sure it compiles/works.
In c and c++ it is possible to use this code:
struct StructExample
{
int x;
int y;
};
struct StructExample a;
a->x = 1;
a->y = 2;
send(FSocket, &a, sizeof(a), 0);

How can I create C-style structs in Clojure?

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.

COM interop: how to use ICustomMarshaler to call 3rd party component

I want to call a method in a COM component from C# using COM interop. This is the methods signature:
long GetPrecursorInfoFromScanNum(long nScanNumber,
LPVARIANT pvarPrecursorInfos,
LPLONG pnArraySize)
and this is sample code (which I checked is really working) to call it in C++:
struct PrecursorInfo
{
double dIsolationMass;
double dMonoIsoMass;
long nChargeState;
long nScanNumber;
};
void CTestOCXDlg::OnOpenParentScansOcx()
{
VARIANT vPrecursorInfos;
VariantInit(&vPrecursorInfos);
long nPrecursorInfos = 0;
m_Rawfile.GetPrecursorInfoFromScanNum(m_nScanNumber,
&vPrecursorInfos,
&nPrecursorInfos);
// Access the safearray buffer
BYTE* pData;
SafeArrayAccessData(vPrecursorInfos.parray, (void**)&pData);
for (int i=0; i < nPrecursorInfos; ++i)
{
// Copy the scan information from the safearray buffer
PrecursorInfo info;
memcpy(&info,
pData + i * sizeof(MS_PrecursorInfo),
sizeof(PrecursorInfo));
}
SafeArrayUnaccessData(vPrecursorInfos.parray);
}
And here's the corresponding C# signature after importing the typelib of the COM component:
void GetPrecursorInfoFromScanNum(int nScanNumber, ref object pvarPrecursorInfos, ref int pnArraySize);
If I'm not mistaken, I need to pass in null for pvarPrecursorInfos to make COM interop marshal it as the expected VT_EMPTY variant. When I'm doing it, I get a SafeArrayTypeMismatchException - not really surprising, looking at how the result is expected to be handled in the sample. So I was trying to use a custom marshaler. Since a cannot alter the component itself, I tried to introduce it this way:
[Guid("06F53853-E43C-4F30-9E5F-D1B3668F0C3C")]
[TypeLibType(4160)]
[ComImport]
public interface IInterfaceNew : IInterfaceOrig
{
[DispId(130)]
int GetPrecursorInfoFromScanNum(int nScanNumber, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshaler))] ref object pvarPrecursorInfos, ref int pnArraySize);
}
The TypeLibType and DispID attribute are the same as in the original version. This works as far as that the MyMarshaller.GetInstance() method is called, but I do not get a callback in MyMarshaller.NativeToManaged. Instead, an access violation is reported. So is this a reliable approach? If yes - how can I make it work? If no: are there any alternatives?
(Just a footnote: in theory I could try to use managed C++ to call the component natively. However, there are lots of other methods in it that work fine with COM interop, so I would very much like to stick with C# if there is any way.)
Since someone asked for it, here's my solution in Managed C++.
array<PrecursorInfo^>^ MSFileReaderExt::GetPrecursorInfo(int scanNumber)
{
VARIANT vPrecursorInfos;
VariantInit(&vPrecursorInfos);
long nPrecursorInfos = -1;
//call the COM component
long rc = pRawFile->GetPrecursorInfoFromScanNum(scanNumber, &vPrecursorInfos, &nPrecursorInfos);
//read the result
//vPrecursorInfos.parray points to a byte sequence
//that can be seen as array of MS_PrecursorInfo instances
//(MS_PrecursorInfo is a struct defined within the COM component)
MS_PrecursorInfo* pPrecursors;
SafeArrayAccessData(vPrecursorInfos.parray, (void**)&pPrecursors);
//now transform into a .NET object
array<PrecursorInfo^>^ infos = gcnew array<PrecursorInfo^>(nPrecursorInfos);
MS_PrecursorInfo currentPrecursor;
for (int i=0; i < nPrecursorInfos; ++i)
{
currentPrecursor = pPrecursors[i];
infos[i] = safe_cast<PrecursorInfo^>(Marshal::PtrToStructure(IntPtr(&currentPrecursor), PrecursorInfo::typeid));
}
SafeArrayUnaccessData(vPrecursorInfos.parray);
return infos;
}
I look at the github code mzLib, which I believe is related to this topic. The code looks good, where it calls
pin_ptr<const wchar_t> wch = PtrToStringChars(path);
I think it may cause some problem, better use
pin_ptr<const wchar_t> pathChar = static_cast<wchar_t*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni(path).ToPointer());
The code then seems to be worked just fine when compiles. However, it might run in problem when imported as dll. I worked on that by adding a constructor,such as
public ref class ThermoDLLClass
{
public:
ThermoDLLClass();
PrecursorInfo GetPrecursorInfo(int scanNum, String^ path);
};
Then, it seems to get precursorInfo and parameters appropriately.